parsav  Diff

Differences From Artifact [4721bcd333]:

To Artifact [9e0d1b7489]:


1
2
3
4
5
6
7
8
9
10
11




12
13
14
15
16
17
18
...
108
109
110
111
112
113
114

115
116
117
118
119
120
121
...
154
155
156
157
158
159
160











161
162
163
164
165
166
167
...
232
233
234
235
236
237
238




239
240
241
242
243
244
245
...
247
248
249
250
251
252
253




254
255
256
257
258
259
260
...
303
304
305
306
307
308
309
310
311

312
313
314
315
316
317
318
...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
...
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655




















656
657
658
659
660
661
662
-- vim: ft=terra
local util = lib.util
local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' }
local pstring = lib.mem.ptr(int8)
local struct srv
local struct cfgcache {
	secret: lib.mem.ptr(int8)
	instance: lib.mem.ptr(int8)
	overlord: &srv
	pol_sec: secmode.t
	pol_reg: bool




}
local struct srv {
	sources: lib.mem.ptr(lib.store.source)
	webmgr: lib.net.mg_mgr
	webcon: &lib.net.mg_connection
	cfg: cfgcache
	id: rawstring
................................................................................
end)

local struct convo {
	srv: &srv
	con: &lib.net.mg_connection
	msg: &lib.net.mg_http_message
	aid: uint64 -- 0 if logged out

	who: &lib.store.actor -- who we're logged in as, if aid ~= 0
	peer: lib.store.inet
	reqtype: lib.http.mime.t -- negotiated content type
-- cache
	navbar: lib.mem.ptr(int8)
	actorcache: lib.mem.cache(lib.mem.ptr(lib.store.actor),32) -- naive cache to avoid unnecessary queries
-- private
................................................................................

	body:send(self.con, 303, [lib.mem.ptr(lib.http.header)] {
		ptr = &hdrs[0], ct = [hdrs.type.N] - lib.trn(cookie == nil,1,0)
	})
end

terra convo:reroute(dest: rawstring) self:reroute_cookie(dest,nil) end











 
terra convo:complain(code: uint16, title: rawstring, msg: rawstring)
	var hdrs = array(
		lib.http.header { key = 'Content-Type', value = 'text/html; charset=UTF-8' },
		lib.http.header { key = 'Cache-Control', value = 'no-store' }
	)

................................................................................
		var r = self.vbofs
		self.vbofs = self.vbofs + o + 1
		@(self.vbofs - 1) = 0
		var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
		return norm.ptr, norm.ct
	else return nil, 0 end
end





terra convo:getv(name: rawstring)
	if self.varbuf.ptr == nil then
		self.varbuf = lib.mem.heapa(int8, self.msg.query.len + self.msg.body.len)
		self.vbofs = self.varbuf.ptr
	end
	var o = lib.net.mg_http_get_var(&self.msg.query, name, self.vbofs, self.varbuf.ct - (self.vbofs - self.varbuf.ptr))
................................................................................
		var r = self.vbofs
		self.vbofs = self.vbofs + o + 1
		@(self.vbofs - 1) = 0
		var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
		return norm.ptr, norm.ct
	else return nil, 0 end
end





local urimatch = macro(function(uri, ptn)
	return `lib.net.mg_globmatch(ptn, [#ptn], uri.ptr, uri.ct+1)
end)

local route = {} -- these are defined in route.t, as they need access to renderers
terra route.dispatch_http ::  {&convo, lib.mem.ptr(int8), lib.http.method.t} -> {}
................................................................................

		switch event do
			case lib.net.MG_EV_HTTP_MSG then
				lib.dbg('routing HTTP request')
				var msg = [&lib.net.mg_http_message](p)
				var co = convo {
					con = con, srv = server, msg = msg;
					aid = 0, who = nil, peer = peer;
					reqtype = lib.http.mime.none;

				} co.varbuf.ptr = nil
				  co.navbar.ptr = nil
				  co.actorcache.top = 0
				  co.actorcache.cur = 0

				-- first, check for an accept header. if it's there, we need to
				-- iterate over the values and pick the highest-priority one
................................................................................
					end
					if val.ptr == nil then goto nocookie end
					val.ct = (cookies + i) - val.ptr
					if lib.str.ncmp(key.ptr, lib.session.cookiename, lib.math.biggest([#lib.session.cookiename], key.ct)) ~= 0 then
						goto nocookie
					end
					::foundcookie:: do
						var aid = lib.session.cookie_interpret(server.cfg.secret,
							[lib.mem.ptr(int8)]{ptr=val.ptr,ct=val.ct},
							lib.osclock.time(nil))
						if aid ~= 0 then co.aid = aid end
					end ::nocookie::;
				end

				if co.aid ~= 0 then
					var sess, usr = co.srv:actor_session_fetch(co.aid, peer)
					if sess.ok == false then co.aid = 0 else
						co.who = usr.ptr
						co.who.rights.powers = server:actor_powers_fetch(co.who.id)
					end
				end

				var uridec = lib.mem.heapa(int8, msg.uri.len) defer uridec:free()
				var urideclen = lib.net.mg_url_decode(msg.uri.ptr, msg.uri.len, uridec.ptr, uridec.ct, 1)
................................................................................
	self.sources:free()
end

terra cfgcache:load()
	self.instance = self.overlord:conf_get('instance-name')
	self.secret = self.overlord:conf_get('server-secret')

	self.pol_reg = false
	var sreg = self.overlord:conf_get('policy-self-register')
	if sreg.ptr ~= nil then
		if lib.str.cmp(sreg.ptr, 'on') == 0
			then self.pol_reg = true
			else self.pol_reg = false
		end
	end
	sreg:free()




















	
	self.pol_sec = secmode.lockdown
	var smode = self.overlord:conf_get('policy-security')
	if smode.ptr ~= nil then
		if lib.str.cmp(smode.ptr, 'public') == 0 then
			self.pol_sec = secmode.public
		elseif lib.str.cmp(smode.ptr, 'private') == 0 then







<
<


>
>
>
>







 







>







 







>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







|

>







 







|


|




|
|







 







|

|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
...
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
-- vim: ft=terra
local util = lib.util
local secmode = lib.enum { 'public', 'private', 'lockdown', 'isolate' }
local pstring = lib.mem.ptr(int8)
local struct srv
local struct cfgcache {
	secret: lib.mem.ptr(int8)


	pol_sec: secmode.t
	pol_reg: bool
	credmgd: bool
	maxupsz: intptr
	instance: lib.mem.ptr(int8)
	overlord: &srv
}
local struct srv {
	sources: lib.mem.ptr(lib.store.source)
	webmgr: lib.net.mg_mgr
	webcon: &lib.net.mg_connection
	cfg: cfgcache
	id: rawstring
................................................................................
end)

local struct convo {
	srv: &srv
	con: &lib.net.mg_connection
	msg: &lib.net.mg_http_message
	aid: uint64 -- 0 if logged out
	aid_issue: lib.store.timepoint
	who: &lib.store.actor -- who we're logged in as, if aid ~= 0
	peer: lib.store.inet
	reqtype: lib.http.mime.t -- negotiated content type
-- cache
	navbar: lib.mem.ptr(int8)
	actorcache: lib.mem.cache(lib.mem.ptr(lib.store.actor),32) -- naive cache to avoid unnecessary queries
-- private
................................................................................

	body:send(self.con, 303, [lib.mem.ptr(lib.http.header)] {
		ptr = &hdrs[0], ct = [hdrs.type.N] - lib.trn(cookie == nil,1,0)
	})
end

terra convo:reroute(dest: rawstring) self:reroute_cookie(dest,nil) end

terra convo:installkey(dest: rawstring, aid: uint64)
	var sesskey: int8[lib.session.maxlen + #lib.session.cookiename + #"=; Path=/" + 1]
	do var p = &sesskey[0]
		p = lib.str.ncpy(p, [lib.session.cookiename .. '='], [#lib.session.cookiename + 1])
		p = p + lib.session.cookie_gen(self.srv.cfg.secret, aid, lib.osclock.time(nil), p)
		lib.dbg('sending cookie ',{&sesskey[0],15})
		p = lib.str.ncpy(p, '; Path=/', 9)
	end
	self:reroute_cookie(dest, &sesskey[0])
end
 
terra convo:complain(code: uint16, title: rawstring, msg: rawstring)
	var hdrs = array(
		lib.http.header { key = 'Content-Type', value = 'text/html; charset=UTF-8' },
		lib.http.header { key = 'Cache-Control', value = 'no-store' }
	)

................................................................................
		var r = self.vbofs
		self.vbofs = self.vbofs + o + 1
		@(self.vbofs - 1) = 0
		var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
		return norm.ptr, norm.ct
	else return nil, 0 end
end
terra convo:ppostv(name: rawstring)
	var s,l = self:postv(name)
	return pstring { ptr = s, ct = l }
end

terra convo:getv(name: rawstring)
	if self.varbuf.ptr == nil then
		self.varbuf = lib.mem.heapa(int8, self.msg.query.len + self.msg.body.len)
		self.vbofs = self.varbuf.ptr
	end
	var o = lib.net.mg_http_get_var(&self.msg.query, name, self.vbofs, self.varbuf.ct - (self.vbofs - self.varbuf.ptr))
................................................................................
		var r = self.vbofs
		self.vbofs = self.vbofs + o + 1
		@(self.vbofs - 1) = 0
		var norm = lib.str.normalize([lib.mem.ptr(int8)]{ptr = r, ct = o})
		return norm.ptr, norm.ct
	else return nil, 0 end
end
terra convo:pgetv(name: rawstring)
	var s,l = self:getv(name)
	return pstring { ptr = s, ct = l }
end

local urimatch = macro(function(uri, ptn)
	return `lib.net.mg_globmatch(ptn, [#ptn], uri.ptr, uri.ct+1)
end)

local route = {} -- these are defined in route.t, as they need access to renderers
terra route.dispatch_http ::  {&convo, lib.mem.ptr(int8), lib.http.method.t} -> {}
................................................................................

		switch event do
			case lib.net.MG_EV_HTTP_MSG then
				lib.dbg('routing HTTP request')
				var msg = [&lib.net.mg_http_message](p)
				var co = convo {
					con = con, srv = server, msg = msg;
					aid = 0, aid_issue = 0, who = nil;
					reqtype = lib.http.mime.none;
					peer = peer;
				} co.varbuf.ptr = nil
				  co.navbar.ptr = nil
				  co.actorcache.top = 0
				  co.actorcache.cur = 0

				-- first, check for an accept header. if it's there, we need to
				-- iterate over the values and pick the highest-priority one
................................................................................
					end
					if val.ptr == nil then goto nocookie end
					val.ct = (cookies + i) - val.ptr
					if lib.str.ncmp(key.ptr, lib.session.cookiename, lib.math.biggest([#lib.session.cookiename], key.ct)) ~= 0 then
						goto nocookie
					end
					::foundcookie:: do
						var aid, tp = lib.session.cookie_interpret(server.cfg.secret,
							[lib.mem.ptr(int8)]{ptr=val.ptr,ct=val.ct},
							lib.osclock.time(nil))
						if aid ~= 0 then co.aid = aid co.aid_issue = tp end
					end ::nocookie::;
				end

				if co.aid ~= 0 then
					var sess, usr = co.srv:actor_session_fetch(co.aid, peer, co.aid_issue)
					if sess.ok == false then co.aid = 0 co.aid_issue = 0 else
						co.who = usr.ptr
						co.who.rights.powers = server:actor_powers_fetch(co.who.id)
					end
				end

				var uridec = lib.mem.heapa(int8, msg.uri.len) defer uridec:free()
				var urideclen = lib.net.mg_url_decode(msg.uri.ptr, msg.uri.len, uridec.ptr, uridec.ct, 1)
................................................................................
	self.sources:free()
end

terra cfgcache:load()
	self.instance = self.overlord:conf_get('instance-name')
	self.secret = self.overlord:conf_get('server-secret')

	do self.pol_reg = false
	var sreg = self.overlord:conf_get('policy-self-register')
	if sreg:ref() then
		if lib.str.cmp(sreg.ptr, 'on') == 0
			then self.pol_reg = true
			else self.pol_reg = false
		end
	end
	sreg:free() end

	do self.credmgd = false
	var sreg = self.overlord:conf_get('credential-store')
	if sreg:ref() then
		if lib.str.cmp(sreg.ptr, 'managed') == 0
			then self.credmgd = true
			else self.credmgd = false
		end
	end
	sreg:free() end

	do self.maxupsz = [1024 * 100] -- 100 kilobyte default
	var sreg = self.overlord:conf_get('maximum-artifact-size')
	if sreg:ref() then
		var sz, ok = lib.math.fsz_parse(sreg)
		if ok then self.maxupsz = sz else
			lib.warn('invalid configuration value for maximum-artifact-size; keeping default 100K upload limit')
		end
	end
	sreg:free() end
	
	self.pol_sec = secmode.lockdown
	var smode = self.overlord:conf_get('policy-security')
	if smode.ptr ~= nil then
		if lib.str.cmp(smode.ptr, 'public') == 0 then
			self.pol_sec = secmode.public
		elseif lib.str.cmp(smode.ptr, 'private') == 0 then