Overview
| Comment: | continued iteration |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
25e05466d5017e26f9260db3969473dc |
| User & Date: | lexi on 2020-12-21 01:08:01 |
| Other Links: | manifest | tags |
Context
|
2020-12-22
| ||
| 23:01 | milestone check-in: 419d1a1ebe user: lexi tags: trunk | |
|
2020-12-21
| ||
| 01:08 | continued iteration check-in: 25e05466d5 user: lexi tags: trunk | |
|
2020-12-16
| ||
| 08:46 | add nix build file check-in: df4ae251ef user: lexi tags: trunk | |
Changes
Modified backend/pgsql.t from [0360541ecf] to [2e402a5b93].
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 ... 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 ... 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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 ... 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
where id = $1::bigint
]];
};
actor_fetch_xid = {
params = {rawstring}, sql = [[
select a.id, a.nym, a.handle, a.origin,
a.bio, a.rank, a.quota, a.key,
coalesce(s.domain,
(select value from parsav_config
where key='domain' limit 1)) as domain
from parsav_actors as a
left join parsav_servers as s
................................................................................
on a.origin = s.id
where $1::text = (a.handle || '@' || domain) or
$1::text = ('@' || a.handle || '@' || domain) or
(a.origin is null and $1::text = ('@' || a.handle))
]];
};
}
local struct pqr {
sz: intptr
res: &lib.pq.PGresult
}
terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
terra pqr:null(row: intptr, col: intptr)
return (lib.pq.PQgetisnull(self.res, row, col) == 1)
end
terra pqr:string(row: intptr, col: intptr)
var v = lib.pq.PQgetvalue(self.res, row, col)
var r: lib.mem.ptr(int8)
r.ct = lib.str.sz(v)
r.ptr = lib.str.ndup(v, r.ct)
return r
end
pqr.methods.int = macro(function(self, ty, row, col)
return quote
var i: ty:astype()
var v = lib.pq.PQgetvalue(self.res, row, col)
lib.math.netswap_ip(ty, v, &i)
in i end
end)
local con = symbol(&lib.pq.PGconn)
local prep = {}
for k,q in pairs(queries) do
local qt = (q.sql):gsub('%s+',' '):gsub('^%s*(.-)%s*$','%1')
local stmt = 'parsavpg_' .. k
prep[#prep + 1] = quote
var res = lib.pq.PQprepare([con], stmt, qt, [#q.params], nil)
defer lib.pq.PQclear(res)
if res == nil or lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_COMMAND_OK then
if res == nil then
lib.bail('grievous error occurred preparing ',k,' statement')
................................................................................
fixers[#fixers + 1] = quote
--lib.io.fmt('uid=%llu(%llx)\n',[args[i]],[args[i]])
[args[i]] = lib.math.netswap(ty, [args[i]])
end
end
end
q.exec = terra(src: &lib.store.source, [args])
var params = arrayof([&int8], [casts])
var params_sz = arrayof(int, [counters])
var params_ft = arrayof(int, [ft])
[fixers]
var res = lib.pq.PQexecPrepared([&lib.pq.PGconn](src.handle), stmt,
[#args], params, params_sz, params_ft, 1)
if res == nil then
................................................................................
return pqr {0, nil}
else
return pqr {ct, res}
end
end
end
local terra row_to_actor(r: &pqr, row: intptr): lib.store.actor
var a = lib.store.actor {
id = r:int(uint64, row, 0);
nym = r:string(row, 1);
handle = r:string(row, 2);
bio = r:string(row, 4);
key = r:string(row, 7);
rights = lib.store.rights_default();
}
a.rights.rank = r:int(uint16, 0, 5);
a.rights.quota = r:int(uint32, 0, 6);
if r:null(0,3) then a.origin = 0
else a.origin = r:int(uint64,0,3) end
return a
end
local b = `lib.store.backend {
id = "pgsql";
open = [terra(src: &lib.store.source): &opaque
lib.report('connecting to postgres database: ', src.string.ptr)
var [con] = lib.pq.PQconnectdb(src.string.ptr)
if lib.pq.PQstatus(con) ~= lib.pq.CONNECTION_OK then
................................................................................
lib.warn('postgres backend connection failed')
lib.pq.PQfinish(con)
return nil
end
var res = lib.pq.PQexec(con, [[
select pg_catalog.set_config('search_path', 'public', false)
]])
if res ~= nil then defer lib.pq.PQclear(res) end
if res == nil or lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_TUPLES_OK then
lib.warn('failed to secure postgres connection')
lib.pq.PQfinish(con)
return nil
end
[prep]
return con
................................................................................
end];
close = [terra(src: &lib.store.source) lib.pq.PQfinish([&lib.pq.PGconn](src.handle)) end];
conf_get = [terra(src: &lib.store.source, key: rawstring)
var r = queries.conf_get.exec(src, key)
if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else
defer r:free()
return r:string(0,0)
end
end];
conf_set = [terra(src: &lib.store.source, key: rawstring, val: rawstring)
queries.conf_set.exec(src, key, val):free() end];
conf_reset = [terra(src: &lib.store.source, key: rawstring)
queries.conf_reset.exec(src, key):free() end];
actor_fetch_uid = [terra(src: &lib.store.source, uid: uint64)
var r = queries.actor_fetch_uid.exec(src, uid)
if r.sz == 0 then
return [lib.stat(lib.store.actor)] { ok = false, error = 1}
else
defer r:free()
var a = [lib.stat(lib.store.actor)] { ok = true }
a.val = row_to_actor(&r, 0)
a.val.source = src
return a
end
end];
}
return b
|
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > | | | | > | | | | > > > > > > > > > > | < | | | > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | < | < | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 159 160 161 162 163 164 165 166 167 168 169 ... 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 ... 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 ... 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 ... 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 |
where id = $1::bigint
]];
};
actor_fetch_xid = {
params = {rawstring}, sql = [[
select a.id, a.nym, a.handle, a.origin,
a.bio, a.rank, a.quota, a.key, $1::text,
coalesce(s.domain,
(select value from parsav_config
where key='domain' limit 1)) as domain
from parsav_actors as a
left join parsav_servers as s
................................................................................
on a.origin = s.id
where $1::text = (a.handle || '@' || domain) or
$1::text = ('@' || a.handle || '@' || domain) or
(a.origin is null and $1::text = ('@' || a.handle))
]];
};
actor_enum_local = {
params = {}, sql = [[
select id, nym, handle, origin,
bio, rank, quota, key,
handle ||'@'||
(select value from parsav_config
where key='domain' limit 1) as xid
from parsav_actors where origin is null
]];
};
actor_enum = {
params = {}, sql = [[
select a.id, a.nym, a.handle, a.origin,
a.bio, a.rank, a.quota, a.key,
a.handle ||'@'||
coalesce(s.domain,
(select value from parsav_config
where key='domain' limit 1)) as xid
from parsav_actors a
left join parsav_servers s on s.id = a.origin
]];
};
}
local struct pqr {
sz: intptr
res: &lib.pq.PGresult
}
terra pqr:free() if self.sz > 0 then lib.pq.PQclear(self.res) end end
terra pqr:null(row: intptr, col: intptr)
return (lib.pq.PQgetisnull(self.res, row, col) == 1)
end
terra pqr:len(row: intptr, col: intptr)
return lib.pq.PQgetlength(self.res, row, col)
end
terra pqr:cols() return lib.pq.PQnfields(self.res) end
terra pqr:string(row: intptr, col: intptr) -- not to be exported!!
var v = lib.pq.PQgetvalue(self.res, row, col)
-- var r: lib.mem.ptr(int8)
-- r.ct = lib.str.sz(v)
-- r.ptr = v
return v
end
terra pqr:bin(row: intptr, col: intptr) -- not to be exported!! DO NOT FREE
return [lib.mem.ptr(uint8)] {
ptr = [&uint8](lib.pq.PQgetvalue(self.res, row, col));
ct = lib.pq.PQgetlength(self.res, row, col);
}
end
terra pqr:String(row: intptr, col: intptr) -- suitable to be exported
var s = [lib.mem.ptr(int8)] { ptr = lib.str.dup(self:string(row,col)) }
s.ct = lib.pq.PQgetlength(self.res, row, col)
return s
end
terra pqr:bool(row: intptr, col: intptr)
var v = lib.pq.PQgetvalue(self.res, row, col)
if @v == 0x01 then return true else return false end
end
terra pqr:cidr(row: intptr, col: intptr)
var v = lib.pq.PQgetvalue(self.res, row, col)
var i: lib.store.inet
if v[0] == 0x02 then i.pv = 4
elseif v[0] == 0x03 then i.pv = 6
else lib.bail('invalid CIDR type in stream') end
i.fixbits = v[1]
if v[2] ~= 0x1 then lib.bail('expected CIDR but got inet from stream') end
if i.pv == 4 and v[3] ~= 0x04 or i.pv == 6 and v[3] ~= 0x10 then
lib.bail('CIDR failed length sanity check') end
var sz: intptr if i.pv == 4 then sz = 4 else sz = 16 end
for j=0,sz do i.v6[j] = v[4 + j] end -- đŹ
return i
end
pqr.methods.int = macro(function(self, ty, row, col)
return quote
var i: ty:astype()
var v = lib.pq.PQgetvalue(self.res, row, col)
lib.math.netswap_ip(ty, v, &i)
in i end
end)
local pqt = {
[lib.store.inet] = function(cidr)
local tycode = cidr and 0x01 or 0x00
return terra(i: lib.store.inet, buf: &uint8)
var sz: intptr
if i.pv == 4 then sz = 4 else sz = 16 end
if buf == nil then buf = [&uint8](lib.mem.heapa_raw(sz + 4)) end
if i.pv == 4 then buf[0] = 0x02
elseif i.pv == 6 then buf[0] = 0x03 end
if cidr then -- our local 'inet' is not quite orthogonal to the
-- postgres inet type; tweak it to match (ignore port)
buf[1] = i.fixbits
elseif i.pv == 6 then buf[1] = 128
else buf[1] = 32 end
buf[2] = tycode
buf[3] = sz
for j=0,sz do buf[4 + j] = i.v6[j] end -- đŹ
return buf
end
end;
}
local con = symbol(&lib.pq.PGconn)
local prep = {}
local sqlsquash = function(s) return s:gsub('%s+',' '):gsub('^%s*(.-)%s*$','%1') end
for k,q in pairs(queries) do
local qt = sqlsquash(q.sql)
local stmt = 'parsavpg_' .. k
prep[#prep + 1] = quote
var res = lib.pq.PQprepare([con], stmt, qt, [#q.params], nil)
defer lib.pq.PQclear(res)
if res == nil or lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_COMMAND_OK then
if res == nil then
lib.bail('grievous error occurred preparing ',k,' statement')
................................................................................
fixers[#fixers + 1] = quote
--lib.io.fmt('uid=%llu(%llx)\n',[args[i]],[args[i]])
[args[i]] = lib.math.netswap(ty, [args[i]])
end
end
end
terra q.exec(src: &lib.store.source, [args])
var params = arrayof([&int8], [casts])
var params_sz = arrayof(int, [counters])
var params_ft = arrayof(int, [ft])
[fixers]
var res = lib.pq.PQexecPrepared([&lib.pq.PGconn](src.handle), stmt,
[#args], params, params_sz, params_ft, 1)
if res == nil then
................................................................................
return pqr {0, nil}
else
return pqr {ct, res}
end
end
end
local terra row_to_actor(r: &pqr, row: intptr): lib.mem.ptr(lib.store.actor)
var a: lib.mem.ptr(lib.store.actor)
if r:cols() >= 8 then
a = [ lib.str.encapsulate(lib.store.actor, {
nym = {`r:string(row, 1); `r:len(row,1) + 1};
handle = {`r:string(row, 2); `r:len(row,2) + 1};
bio = {`r:string(row, 4); `r:len(row,4) + 1};
xid = {`r:string(row, 8); `r:len(row,8) + 1};
}) ]
else
a = [ lib.str.encapsulate(lib.store.actor, {
nym = {`r:string(row, 1); `r:len(row,1) + 1};
handle = {`r:string(row, 2); `r:len(row,2) + 1};
bio = {`r:string(row, 4); `r:len(row,4) + 1};
}) ]
a.ptr.xid = nil
end
a.ptr.id = r:int(uint64, row, 0);
a.ptr.rights = lib.store.rights_default();
a.ptr.rights.rank = r:int(uint16, row, 5);
a.ptr.rights.quota = r:int(uint32, row, 6);
if r:null(row,7) then
a.ptr.key.ct = 0 a.ptr.key.ptr = nil
else
a.ptr.key = r:bin(row,7)
end
if r:null(row,3) then a.ptr.origin = 0
else a.ptr.origin = r:int(uint64,row,3) end
return a
end
local checksha = function(hnd, query, hash, origin, username, pw)
local inet_buf = symbol(uint8[4 + 16])
local validate = function(kind, cred, credlen)
return quote
var osz: intptr if origin.pv == 4 then osz = 4 else osz = 16 end
var formats = arrayof([int], 1,1,1,1)
var params = arrayof([&int8], username, kind,
[&int8](&cred), [&int8](&inet_buf))
var lens = arrayof(int, lib.str.sz(username), [#kind], credlen, osz + 4)
var res = lib.pq.PQexecParams([&lib.pq.PGconn](hnd), query, 4, nil,
params, lens, formats, 1)
if res == nil then
lib.bail('grievous failure checking pwhash')
elseif lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_TUPLES_OK then
lib.warn('pwhash query failed: ', lib.pq.PQresultErrorMessage(res), '\n', query)
else
var r = pqr {
sz = lib.pq.PQntuples(res);
res = res;
}
if r.sz > 0 then -- found a record! stop here
var aid = r:int(uint64, 0,0)
r:free()
return aid
end
end
end
end
local out = symbol(uint8[64])
local vdrs = {}
local alg = lib.md['MBEDTLS_MD_SHA' .. tostring(hash)]
vdrs[#vdrs+1] = quote
if lib.md.mbedtls_md(lib.md.mbedtls_md_info_from_type(alg),
[&uint8](pw), lib.str.sz(pw), out) ~= 0 then
lib.bail('hashing failure!')
end
[ validate(string.format('pw-sha%u', hash), out, hash / 8) ]
end
return quote
lib.dbg(['searching for hashed password credentials in format SHA' .. tostring(hash)])
var [inet_buf]
[pqt[lib.store.inet](false)](origin, inet_buf)
var [out]
[vdrs]
lib.dbg(['could not find password hash'])
end
end
local b = `lib.store.backend {
id = "pgsql";
open = [terra(src: &lib.store.source): &opaque
lib.report('connecting to postgres database: ', src.string.ptr)
var [con] = lib.pq.PQconnectdb(src.string.ptr)
if lib.pq.PQstatus(con) ~= lib.pq.CONNECTION_OK then
................................................................................
lib.warn('postgres backend connection failed')
lib.pq.PQfinish(con)
return nil
end
var res = lib.pq.PQexec(con, [[
select pg_catalog.set_config('search_path', 'public', false)
]])
if res == nil then
lib.warn('critical failure to secure postgres connection')
lib.pq.PQfinish(con)
return nil
end
defer lib.pq.PQclear(res)
if lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_TUPLES_OK then
lib.warn('failed to secure postgres connection')
lib.pq.PQfinish(con)
return nil
end
[prep]
return con
................................................................................
end];
close = [terra(src: &lib.store.source) lib.pq.PQfinish([&lib.pq.PGconn](src.handle)) end];
conf_get = [terra(src: &lib.store.source, key: rawstring)
var r = queries.conf_get.exec(src, key)
if r.sz == 0 then return [lib.mem.ptr(int8)] { ptr = nil, ct = 0 } else
defer r:free()
return r:String(0,0)
end
end];
conf_set = [terra(src: &lib.store.source, key: rawstring, val: rawstring)
queries.conf_set.exec(src, key, val):free() end];
conf_reset = [terra(src: &lib.store.source, key: rawstring)
queries.conf_reset.exec(src, key):free() end];
actor_fetch_uid = [terra(src: &lib.store.source, uid: uint64)
var r = queries.actor_fetch_uid.exec(src, uid)
if r.sz == 0 then
return [lib.mem.ptr(lib.store.actor)] { ct = 0, ptr = nil }
else defer r:free()
var a = row_to_actor(&r, 0)
a.ptr.source = src
return a
end
end];
actor_enum = [terra(src: &lib.store.source)
var r = queries.actor_enum.exec(src)
if r.sz == 0 then
return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
else defer r:free()
var mem = lib.mem.heapa([&lib.store.actor], r.sz)
for i=0,r.sz do mem.ptr[i] = row_to_actor(&r, i).ptr end
return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
end
end];
actor_enum_local = [terra(src: &lib.store.source)
var r = queries.actor_enum_local.exec(src)
if r.sz == 0 then
return [lib.mem.ptr(&lib.store.actor)] { ct = 0, ptr = nil }
else defer r:free()
var mem = lib.mem.heapa([&lib.store.actor], r.sz)
for i=0,r.sz do mem.ptr[i] = row_to_actor(&r, i).ptr end
return [lib.mem.ptr(&lib.store.actor)] { ct = r.sz, ptr = mem.ptr }
end
end];
actor_auth_how = [terra(
src: &lib.store.source,
ip: lib.store.inet,
username: rawstring
)
var authview = src:conf_get('auth-source') defer authview:free()
var a: lib.str.acc defer a:free()
a:compose('with mts as (select a.kind from ',authview,[' ' .. sqlsquash [[as a
left join parsav_actors as u on u.id = a.uid
where (a.uid is null or u.handle = $1::text or (
a.uid = 0 and a.name = $1::text
)) and
(a.netmask is null or a.netmask >> $2::inet) and
blacklist = false)
select
(select count(*) from mts where kind like 'pw-%') > 0,
(select count(*) from mts where kind like 'otp-%') > 0,
(select count(*) from mts where kind like 'challenge-%') > 0,
(select count(*) from mts where kind = 'trust') > 0 ]]]) -- cheat
var cs: lib.store.credset cs:clear();
var ipbuf: int8[20]
;[pqt[lib.store.inet](false)](ip, [&uint8](&ipbuf))
var ipbl: intptr if ip.pv == 4 then ipbl = 8 else ipbl = 20 end
var params = arrayof(rawstring, username, [&int8](&ipbuf))
var params_sz = arrayof(int, lib.str.sz(username), ipbl)
var params_ft = arrayof(int, 1, 1)
var res = lib.pq.PQexecParams([&lib.pq.PGconn](src.handle), a.buf, 2, nil,
params, params_sz, params_ft, 1)
if res == nil or lib.pq.PQresultStatus(res) ~= lib.pq.PGRES_TUPLES_OK then
if res == nil then
lib.bail('grievous error occurred checking for auth methods')
end
lib.bail('could not get auth methods for user ',username,':\n',lib.pq.PQresultErrorMessage(res))
end
var r = pqr { res = res, sz = lib.pq.PQntuples(res) }
if r.sz == 0 then return cs end -- just in case
(cs.pw << r:bool(0,0))
(cs.otp << r:bool(0,1))
(cs.challenge << r:bool(0,2))
(cs.trust << r:bool(0,3))
lib.pq.PQclear(res)
return cs
end];
actor_auth_pw = [terra(
src: &lib.store.source,
ip: lib.store.inet,
username: rawstring,
cred: rawstring
)
var authview = src:conf_get('auth-source') defer authview:free()
var a: lib.str.acc defer a:free()
a:compose('select a.aid from ',authview,[' ' .. sqlsquash [[as a
left join parsav_actors as u on u.id = a.uid
where (a.uid is null or u.handle = $1::text or (
a.uid = 0 and a.name = $1::text
)) and
(a.kind = 'trust' or (a.kind = $2::text and a.cred = $3::bytea)) and
(a.netmask is null or a.netmask >> $4::inet)
order by blacklist desc limit 1]]])
[ checksha(`src.handle, `a.buf, 256, ip, username, cred) ] -- most common
[ checksha(`src.handle, `a.buf, 512, ip, username, cred) ] -- most secure
[ checksha(`src.handle, `a.buf, 384, ip, username, cred) ] -- weird
[ checksha(`src.handle, `a.buf, 224, ip, username, cred) ] -- weirdest
-- TODO: check pbkdf2-hmac
-- TODO: check OTP
return 0
end];
}
return b
|
Modified cmdparse.t from [c7f162fae3] to [bad20dd1d0].
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 |
local helpstr = 'usage: parsav [-' .. flags .. '] [<arg>...]\n'
options.entries = {
{field = 'arglist', type = lib.mem.ptr(rawstring)}
}
local shortcases, longcases, init = {}, {}, {}
local self = symbol(&options)
local arg = symbol(rawstring)
local skip = label()
for o,desc in pairs(tbl) do
options.entries[#options.entries + 1] = {
field = o, type = bool
}
helpstr = helpstr .. string.format(' -%s --%s: %s\n',
desc[1], o, desc[2])
end
for o,desc in pairs(tbl) do
local flag = desc[1]
init[#init + 1] = quote [self].[o] = false end
shortcases[#shortcases + 1] = quote
case [int8]([string.byte(flag)]) then [self].[o] = true end
end
longcases[#longcases + 1] = quote
if lib.str.cmp([arg]+2, o) == 0 then
[self].[o] = true
goto [skip]
end
end
end
options.methods.parse = terra([self], argc: int, argv: &rawstring)
[init]
var parseopts = true
self.arglist = lib.mem.heapa(rawstring, argc)
var finalargc = 0
for i=0,argc do
var [arg] = argv[i]
if arg[0] == ('-')[0] and parseopts then
if arg[1] == ('-')[0] then -- long option
if arg[2] == 0 then -- last option
parseopts = false
else [longcases] end
else -- short options
|
> > > | < > > | > > > > > > | | < < | | < > > | |
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 |
local helpstr = 'usage: parsav [-' .. flags .. '] [<arg>...]\n'
options.entries = {
{field = 'arglist', type = lib.mem.ptr(rawstring)}
}
local shortcases, longcases, init = {}, {}, {}
local self = symbol(&options)
local arg = symbol(rawstring)
local idxo = symbol(uint)
local skip = label()
local sanitize = function(s) return s:gsub('_','-') end
for o,desc in pairs(tbl) do
local consume = desc[3] or 0
options.entries[#options.entries + 1] = {
field = o, type = (consume > 0) and uint or bool
}
helpstr = helpstr .. string.format(' -%s --%s: %s\n',
desc[1], sanitize(o), desc[2])
end
for o,desc in pairs(tbl) do
local flag = desc[1]
local consume = desc[3] or 0
init[#init + 1] = quote [self].[o] = [consume > 0 and 0 or false] end
local ch if consume > 0 then ch = quote
[self].[o] = idxo
idxo = idxo + consume
end else ch = quote
[self].[o] = true
end end
shortcases[#shortcases + 1] = quote
case [int8]([string.byte(flag)]) then [ch] end
end
longcases[#longcases + 1] = quote
if lib.str.cmp([arg]+2, [sanitize(o)]) == 0 then [ch] goto [skip] end
end
end
terra options:free() self.arglist:free() end
options.methods.parse = terra([self], argc: int, argv: &rawstring)
[init]
var parseopts = true
var [idxo] = 1
self.arglist = lib.mem.heapa(rawstring, argc)
var finalargc = 0
for i=1,argc do
var [arg] = argv[i]
if arg[0] == ('-')[0] and parseopts then
if arg[1] == ('-')[0] then -- long option
if arg[2] == 0 then -- last option
parseopts = false
else [longcases] end
else -- short options
|
Modified config.lua from [60797f7bc4] to [53779583db].
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
end
end
local posixes = {
linux = true; osx = true;
android = true; haiku = true;
}
local default_os = 'linux'
local conf = {
pkg = {};
dist = default('parsav_dist', coalesce(
os.getenv('NIX_PATH') and 'nixos',
os.getenv('NIX_STORE') and 'nixos',
''));
tgttrip = default('parsav_arch_triple'); -- target triple, used in xcomp
................................................................................
endian = default('parsav_arch_endian', 'little');
build = {
id = u.rndstr(6);
release = u.ingest('release');
when = os.date();
};
feat = {};
}
if u.ping '.fslckout' or u.ping '_FOSSIL_' then
if u.ping '_FOSSIL_' then default_os = 'windows' end
conf.build.branch = u.exec { 'fossil', 'branch', 'current' }
conf.build.checkout = (u.exec { 'fossil', 'sql',
[[select value from localdb.vvar where name = 'checkout-hash']]
}):gsub("^'(.*)'$", '%1')
|
>
>
>
>
>
>
>
>
>
>
|
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
end
end
local posixes = {
linux = true; osx = true;
android = true; haiku = true;
}
local default_os = 'linux'
local defaultlist = function(env, ...)
local e = os.getenv(env)
local lst = {}
if e then
for v in e:gmatch('([^:]*)') do lst[#lst + 1] = v end
return lst
else return {...} end
end
local conf = {
pkg = {};
dist = default('parsav_dist', coalesce(
os.getenv('NIX_PATH') and 'nixos',
os.getenv('NIX_STORE') and 'nixos',
''));
tgttrip = default('parsav_arch_triple'); -- target triple, used in xcomp
................................................................................
endian = default('parsav_arch_endian', 'little');
build = {
id = u.rndstr(6);
release = u.ingest('release');
when = os.date();
};
feat = {};
backends = defaultlist('parsav_backends', 'pgsql');
braingeniousmode = false;
}
if u.ping '.fslckout' or u.ping '_FOSSIL_' then
if u.ping '_FOSSIL_' then default_os = 'windows' end
conf.build.branch = u.exec { 'fossil', 'branch', 'current' }
conf.build.checkout = (u.exec { 'fossil', 'sql',
[[select value from localdb.vvar where name = 'checkout-hash']]
}):gsub("^'(.*)'$", '%1')
|
Modified crypt.t from [340864c560] to [709e2a6426].
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
132
133
134
135
136
137
138
139
140
|
end;
toobig = -lib.pk.MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
}
const.maxpemsz = math.floor((const.keybits / 8)*6.4) + 128 -- idk why this formula works but it basically seems to
local ctx = lib.pk.mbedtls_pk_context
local m = {
pemfile = uint8[const.maxpemsz];
}
local callbacks = {}
if config.feat.randomizer == 'kern' then
local rnd = terralib.externfunction('getrandom', {&opaque, intptr, uint} -> ptrdiff);
terra callbacks.randomize(ctx: &opaque, dest: &uint8, sz: intptr): int
return rnd(dest, sz, 0)
end
................................................................................
if lib.pk.mbedtls_pk_verify(pk, hk, hash, 0, [&uint8](sig), siglen) == 0 then
return true, secl
end
end
lib.dbg('all hash algorithms failed')
return false, 0
end
return m
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
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
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
end; toobig = -lib.pk.MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; } const.maxpemsz = math.floor((const.keybits / 8)*6.4) + 128 -- idk why this formula works but it basically seems to local ctx = lib.pk.mbedtls_pk_context local struct hashalg { id: uint8 bytes: intptr } local m = { pemfile = uint8[const.maxpemsz]; alg = { sha1 = `hashalg {id = lib.md.MBEDTLS_MD_SHA1; bytes = 160/8}; sha256 = `hashalg {id = lib.md.MBEDTLS_MD_SHA256; bytes = 256/8}; sha512 = `hashalg {id = lib.md.MBEDTLS_MD_SHA512; bytes = 512/8}; sha384 = `hashalg {id = lib.md.MBEDTLS_MD_SHA384; bytes = 384/8}; sha224 = `hashalg {id = lib.md.MBEDTLS_MD_SHA224; bytes = 224/8}; -- md5 = {id = lib.md.MBEDTLS_MD_MD5};-- !!! }; } local callbacks = {} if config.feat.randomizer == 'kern' then local rnd = terralib.externfunction('getrandom', {&opaque, intptr, uint} -> ptrdiff); terra callbacks.randomize(ctx: &opaque, dest: &uint8, sz: intptr): int return rnd(dest, sz, 0) end ................................................................................ if lib.pk.mbedtls_pk_verify(pk, hk, hash, 0, [&uint8](sig), siglen) == 0 then return true, secl end end lib.dbg('all hash algorithms failed') return false, 0 end terra m.hmac(alg: hashalg, key: lib.mem.ptr(uint8), txt: lib.mem.ptr(int8), buf: &uint8) lib.md.mbedtls_md_hmac( lib.md.mbedtls_md_info_from_type(alg.id), key.ptr, key.ct, [&uint8](txt.ptr), txt.ct, buf) -- sz(buf) >= hash output size end terra m.hmaca(alg: hashalg, key: lib.mem.ptr(uint8), txt: lib.mem.ptr(int8)) var buf = lib.mem.heapa(uint8, alg.bytes) m.hmac(alg, key, txt, buf.ptr) return buf end terra m.hotp(key: &(uint8[10]), counter: uint64) var hmac: uint8[20] var ctr = [lib.mem.ptr(int8)]{ptr = [&int8](&counter), ct = 8} m.hmac(m.alg.sha1, [lib.mem.ptr(uint8)]{ptr = [&uint8](key), ct = 10}, ctr, hmac) var ofs = hmac[19] and 0x0F var p: uint8[4] for i=0,4 do p[i] = hmac[ofs + i] end return (@[&uint32](&p)) and 0x7FFFFFFF -- one hopes it's that easy end return m |
Added license.de version [34fb6d78d2].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 |
OPEN-SOURCE-LIZENZ FĂR DIE EUROPĂISCHE UNION v. 1.2 EUPL © EuropĂ€ische Union 2007, 2016 Diese Open-Source-Lizenz fĂŒr die EuropĂ€ische Union (âEUPLâ) gilt fĂŒr Werke (im Sinne der nachfolgenden Begriffsbestimmung), die unter EUPL-Bedingungen zur VerfĂŒgung gestellt werden. Das Werk darf nur in der durch diese Lizenz gestatteten Form genutzt werden (insoweit eine solche Nutzung dem Urheber vorbehalten ist). Das Werk wird unter den Bedingungen dieser Lizenz zur VerfĂŒgung gestellt, wenn der Lizenzgeber (im Sinne der nachfolgenden Begriffsbestimmung) den folgenden Hinweis unmittelbar hinter dem Urheberrechtshinweis dieses Werks anbringt: Lizenziert unter der EUPL oder in einer anderen Form zum Ausdruck bringt, dass er es unter der EUPL lizenzieren möchte. 1.Begriffsbestimmungen FĂŒr diese Lizenz gelten folgende Begriffsbestimmungen: â âLizenzâ:diese Lizenz. â âOriginalwerkâ:das Werk oder die Software, die vom Lizenzgeber unter dieser Lizenz verbreitet oder zugĂ€nglich gemacht wird, und zwar als Quellcode und gegebenenfalls auch als ausfĂŒhrbarer Code. â âBearbeitungenâ:die Werke oder Software, die der Lizenznehmer auf der Grundlage des Originalwerks oder seiner Bearbeitungen schaffen kann. In dieser Lizenz wird nicht festgelegt, wie umfangreich die Ănderung oder wie stark die AbhĂ€ngigkeit vom Originalwerk fĂŒr eine Einstufung als Bearbeitung sein muss; dies bestimmt sich nach dem Urheberrecht, das in dem unter Artikel 15 aufgefĂŒhrten Land anwendbar ist. â âWerkâ:das Originalwerk oder seine Bearbeitungen. â âQuellcodeâ:diejenige Form des Werkes, die zur Auffassung durch den Menschen bestimmt ist und die am besten geeignet ist, um vom Menschen verstanden und verĂ€ndert zu werden. â âAusfĂŒhrbarer Codeâ:die â ĂŒblicherweise â kompilierte Form des Werks, die von einem Computer als Programm ausgefĂŒhrt werden soll. â âLizenzgeberâ:die natĂŒrliche oder juristische Person, die das Werk unter der Lizenz verbreitet oder zugĂ€nglich macht. â âBearbeiterâ:jede natĂŒrliche oder juristische Person, die das Werk unter der Lizenz verĂ€ndert oder auf andere Weise zur Schaffung einer Bearbeitung beitrĂ€gt. â âLizenznehmerâ (âSieâ):jede natĂŒrliche oder juristische Person, die das Werk unter den Lizenzbedingungen nutzt. â âVerbreitungâ oder âZugĂ€nglichmachungâ:alle Formen von Verkauf, Ăberlassung, Verleih, Vermietung, Verbreitung, Weitergabe, Ăbermittlung oder anderweitiger Online- oder Offline-Bereitstellung von VervielfĂ€ltigungen des Werks oder ZugĂ€nglichmachung seiner wesentlichen Funktionen fĂŒr dritte natĂŒrliche oder juristische Personen. 2.Umfang der Lizenzrechte Der Lizenzgeber erteilt Ihnen hiermit fĂŒr die GĂŒltigkeitsdauer der am Originalwerk bestehenden Urheberrechte eine weltweite, unentgeltliche, nicht ausschlieĂliche, unterlizenzierbare Lizenz, die Sie berechtigt: â das Werk uneingeschrĂ€nkt zu nutzen, â das Werk zu vervielfĂ€ltigen, â das Werk zu verĂ€ndern und Bearbeitungen auf der Grundlage des Werks zu schaffen, â das Werk öffentlich zugĂ€nglich zu machen, was das Recht einschlieĂt, das Werk oder VervielfĂ€ltigungsstĂŒcke davon öffentlich bereitzustellen oder wahrnehmbar zu machen oder das Werk, soweit möglich, öffentlich aufzufĂŒhren, â das Werk oder VervielfĂ€ltigungen davon zu verbreiten, â das Werk oder VervielfĂ€ltigungen davon zu vermieten oder zu verleihen, â das Werk oder VervielfĂ€ltigungen davon weiter zu lizenzieren. FĂŒr die Wahrnehmung dieser Rechte können beliebige, derzeit bekannte oder kĂŒnftige Medien, TrĂ€ger und Formate verwendet werden, soweit das geltende Recht dem nicht entgegensteht. FĂŒr die LĂ€nder, in denen Urheberpersönlichkeitsrechte an dem Werk bestehen, verzichtet der Lizenzgeber im gesetzlich zulĂ€ssigen Umfang auf seine Urheberpersönlichkeitsrechte, um die Lizenzierung der oben aufgefĂŒhrten Verwertungsrechte wirksam durchfĂŒhren zu können. Der Lizenzgeber erteilt dem Lizenznehmer ein nicht ausschlieĂliches, unentgeltliches Nutzungsrecht an seinen Patenten, sofern dies zur AusĂŒbung der durch die Lizenz erteilten Nutzungsrechte am Werk notwendig ist. 3.ZugĂ€nglichmachung des Quellcodes Der Lizenzgeber kann das Werk entweder als Quellcode oder als ausfĂŒhrbaren Code zur VerfĂŒgung stellen. Stellt er es als ausfĂŒhrbaren Code zur VerfĂŒgung, so stellt er darĂŒber hinaus eine maschinenlesbare Kopie des Quellcodes fĂŒr jedes von ihm verbreitete VervielfĂ€ltigungsstĂŒck des Werks zur VerfĂŒgung, oder er verweist in einem Vermerk im Anschluss an den dem Werk beigefĂŒgten Urheberrechtshinweis auf einen Speicherort, an dem problemlos und unentgeltlich auf den Quellcode zugegriffen werden kann, solange der Lizenzgeber das Werk verbreitet oder zugĂ€nglich macht. 4.EinschrĂ€nkungen des Urheberrechts Es ist nicht Zweck dieser Lizenz, Ausnahmen oder Schranken der ausschlieĂlichen Rechte des Urhebers am Werk, die dem Lizenznehmer zugutekommen, einzuschrĂ€nken. Auch die Erschöpfung dieser Rechte bleibt von dieser Lizenz unberĂŒhrt. 5.Pflichten des Lizenznehmers Die EinrĂ€umung der oben genannten Rechte ist an mehrere BeschrĂ€nkungen und Pflichten fĂŒr den Lizenznehmer gebunden: Urheberrechtshinweis, Lizenztext, Nennung des Bearbeiters: Der Lizenznehmer muss alle Urheberrechts-, Patent- oder Markenrechtshinweise und alle Hinweise auf die Lizenz und den Haftungsausschluss unverĂ€ndert lassen. Jedem von ihm verbreiteten oder zugĂ€nglich gemachten VervielfĂ€ltigungsstĂŒck des Werks muss der Lizenznehmer diese Hinweise sowie diese Lizenz beifĂŒgen. Der Lizenznehmer muss auf jedem abgeleiteten Werk deutlich darauf hinweisen, dass das Werk geĂ€ndert wurde, und das Datum der Bearbeitung angeben. âCopyleftâ-Klausel: Der Lizenznehmer darf VervielfĂ€ltigungen des Originalwerks oder Bearbeitungen nur unter den Bedingungen dieser EUPL oder einer neueren Version dieser Lizenz verbreiten oder zugĂ€nglich machen, auĂer wenn das Originalwerk ausdrĂŒcklich nur unter dieser Lizenzversion â z. B. mit der Angabe âNur EUPL V. 1.2â â verbreitet werden darf. Der Lizenznehmer (der zum Lizenzgeber wird) darf fĂŒr das Werk oder die Bearbeitung keine zusĂ€tzlichen Bedingungen anbieten oder vorschreiben, die die Bedingungen dieser Lizenz verĂ€ndern oder einschrĂ€nken. KompatibilitĂ€ts-Klausel: Wenn der Lizenznehmer Bearbeitungen, die auf dem Werk und einem anderen Werk, das unter einer kompatiblen Lizenz lizenziert wurde, basieren, oder die Kopien dieser Bearbeitungen verbreitet oder zugĂ€nglich macht, kann dies unter den Bedingungen dieser kompatiblen Lizenz erfolgen. Unter âkompatibler Lizenzâ ist eine im Anhang dieser Lizenz angefĂŒhrte Lizenz zu verstehen. Sollten die Verpflichtungen des Lizenznehmers aus der kompatiblen Lizenz mit denjenigen aus der vorliegenden Lizenz (EUPL) in Konflikt stehen, werden die Verpflichtungen aus der kompatiblen Lizenz Vorrang haben. Bereitstellung des Quellcodes: Wenn der Lizenznehmer VervielfĂ€ltigungsstĂŒcke des Werks verbreitet oder zugĂ€nglich macht, muss er eine maschinenlesbare Fassung des Quellcodes mitliefern oder einen Speicherort angeben, ĂŒber den problemlos und unentgeltlich so lange auf diesen Quellcode zugegriffen werden kann, wie der Lizenznehmer das Werk verbreitet oder zugĂ€nglich macht. Rechtsschutz: Diese Lizenz erlaubt nicht die Benutzung von Kennzeichen, Marken oder geschĂŒtzten Namensrechten des Lizenzgebers, soweit dies nicht fĂŒr die angemessene und ĂŒbliche Beschreibung der Herkunft des Werks und der inhaltlichen Wiedergabe des Urheberrechtshinweises erforderlich ist. 6.Urheber und Bearbeiter Der ursprĂŒngliche Lizenzgeber gewĂ€hrleistet, dass er das Urheberrecht am Originalwerk innehat oder dieses an ihn lizenziert wurde und dass er befugt ist, diese Lizenz zu erteilen. Jeder Bearbeiter gewĂ€hrleistet, dass er das Urheberrecht an den von ihm vorgenommenen Ănderungen des Werks besitzt und befugt ist, diese Lizenz zu erteilen. Jedes Mal, wenn Sie die Lizenz annehmen, erteilen Ihnen der ursprĂŒngliche Lizenzgeber und alle folgenden Bearbeiter eine Befugnis zur Nutzung ihrer BeitrĂ€ge zum Werk unter den Bedingungen dieser Lizenz. 7.GewĂ€hrleistungsausschluss Die Arbeit an diesem Werk wird laufend fortgefĂŒhrt; es wird durch unzĂ€hlige Bearbeiter stĂ€ndig verbessert. Das Werk ist nicht vollendet und kann daher Fehler (âbugsâ) enthalten, die dieser Art der Entwicklung inhĂ€rent sind. Aus den genannten GrĂŒnden wird das Werk unter dieser Lizenz âso, wie es istâ ohne jegliche GewĂ€hrleistung zur VerfĂŒgung gestellt. Dies gilt unter anderem â aber nicht ausschlieĂlich â fĂŒr Marktreife, Verwendbarkeit fĂŒr einen bestimmten Zweck, MĂ€ngelfreiheit, Richtigkeit sowie Nichtverletzung von anderen ImmaterialgĂŒterrechten als dem Urheberrecht (vgl. dazu Artikel 6 dieser Lizenz). Dieser GewĂ€hrleistungsausschluss ist wesentlicher Bestandteil der Lizenz und Bedingung fĂŒr die EinrĂ€umung von Rechten an dem Werk. 8.Haftungsausschluss/HaftungsbeschrĂ€nkung AuĂer in FĂ€llen von Vorsatz oder der Verursachung von PersonenschĂ€den haftet der Lizenzgeber nicht fĂŒr direkte oder indirekte, materielle oder immaterielle SchĂ€den irgendwelcher Art, die aus der Lizenz oder der Benutzung des Werks folgen; dies gilt unter anderem, aber nicht ausschlieĂlich, fĂŒr Firmenwertverluste, Produktionsausfall, Computerausfall oder Computerfehler, Datenverlust oder wirtschaftliche SchĂ€den, und zwar auch dann, wenn der Lizenzgeber auf die Möglichkeit solcher SchĂ€den hingewiesen wurde. UnabhĂ€ngig davon haftet der Lizenzgeber im Rahmen der gesetzlichen Produkthaftung, soweit die entsprechenden Regelungen auf das Werk anwendbar sind. 9.Zusatzvereinbarungen Wenn Sie das Werk verbreiten, können Sie Zusatzvereinbarungen schlieĂen, in denen Verpflichtungen oder Dienstleistungen festgelegt werden, die mit dieser Lizenz vereinbar sind. Sie dĂŒrfen Verpflichtungen indessen nur in Ihrem eigenen Namen und auf Ihre eigene Verantwortung eingehen, nicht jedoch im Namen des ursprĂŒnglichen Lizenzgebers oder eines anderen Bearbeiters, und nur, wenn Sie sich gegenĂŒber allen Bearbeitern verpflichten, sie zu entschĂ€digen, zu verteidigen und von der Haftung freizustellen, falls aufgrund der von Ihnen eingegangenen GewĂ€hrleistungsverpflichtung oder HaftungsĂŒbernahme Forderungen gegen sie geltend gemacht werden oder eine Haftungsverpflichtung entsteht. 10.Annahme der Lizenz Sie können den Bestimmungen dieser Lizenz zustimmen, indem Sie das Symbol âLizenz annehmenâ unter dem Fenster mit dem Lizenztext anklicken oder indem Sie Ihre Zustimmung auf vergleichbare Weise in einer nach anwendbarem Recht zulĂ€ssigen Form geben. Das Anklicken des Symbols gilt als Anzeichen Ihrer eindeutigen und unwiderruflichen Annahme der Lizenz und der darin enthaltenen Klauseln und Bedingungen. In gleicher Weise gilt als Zeichen der eindeutigen und unwiderruflichen Zustimmung die AusĂŒbung eines Rechtes, das in Artikel 2 dieser Lizenz angefĂŒhrt ist, wie das Erstellen einer Bearbeitung oder die Verbreitung oder ZugĂ€nglichmachung des Werks oder dessen VervielfĂ€ltigungen. 11.Informationspflichten Wenn Sie das Werk verbreiten oder zugĂ€nglich machen (beispielsweise, indem Sie es zum Herunterladen von einer Website anbieten), mĂŒssen Sie ĂŒber den Vertriebskanal oder das benutzte Verbreitungsmedium der Ăffentlichkeit zumindest jene Informationen bereitstellen, die nach dem anwendbaren Recht bezĂŒglich der Lizenzgeber, der Lizenz und ihrer ZugĂ€nglichkeit, des Abschlusses des Lizenzvertrags sowie darĂŒber, wie die Lizenz durch den Lizenznehmer gespeichert und vervielfĂ€ltigt werden kann, erforderlich sind. 12.Beendigung der Lizenz Die Lizenz und die damit eingerĂ€umten Rechte erlöschen automatisch, wenn der Lizenznehmer gegen die Lizenzbedingungen verstöĂt. Ein solches Erlöschen der Lizenz fĂŒhrt nicht zum Erlöschen der Lizenzen von Personen, denen das Werk vom Lizenznehmer unter dieser Lizenz zur VerfĂŒgung gestellt worden ist, solange diese Personen die Lizenzbedingungen erfĂŒllen. 13.Sonstiges Unbeschadet des Artikels 9 stellt die Lizenz die vollstĂ€ndige Vereinbarung der Parteien ĂŒber das Werk dar. Sind einzelne Bestimmungen der Lizenz nach geltendem Recht nichtig oder unwirksam, so berĂŒhrt dies nicht die Wirksamkeit oder Durchsetzbarkeit der Lizenz an sich. Solche Bestimmungen werden vielmehr so ausgelegt oder modifiziert, dass sie wirksam und durchsetzbar sind. Die EuropĂ€ische Kommission kann weitere Sprachfassungen oder neue Versionen dieser Lizenz oder aktualisierte Fassungen des Anhangs veröffentlichen, soweit dies notwendig und angemessen ist, ohne den Umfang der Lizenzrechte zu verringern. Neue Versionen werden mit einer eindeutigen Versionsnummer veröffentlicht. Alle von der EuropĂ€ischen Kommission anerkannten Sprachfassungen dieser Lizenz sind gleichwertig. Die Parteien können sich auf die Sprachfassung ihrer Wahl berufen. 14.Gerichtsstand Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: â FĂŒr alle Streitigkeiten ĂŒber die Auslegung dieser Lizenz zwischen den Organen, Einrichtungen und sonstigen Stellen der EuropĂ€ischen Union als Lizenzgeber und einem Lizenznehmer ist der Gerichtshof der EuropĂ€ischen Union gemÀà Artikel 272 des Vertrags ĂŒber die Arbeitsweise der EuropĂ€ischen Union zustĂ€ndig; â Gerichtsstand fĂŒr Streitigkeiten zwischen anderen Parteien ĂŒber die Auslegung dieser Lizenz ist allein der Ort, an dem der Lizenzgeber seinen Wohnsitz oder den wirtschaftlichen Mittelpunkt seiner TĂ€tigkeit hat. 15.Anwendbares Recht Unbeschadet besonderer Vereinbarungen zwischen den Parteien gilt Folgendes: â Diese Lizenz unterliegt dem Recht des Mitgliedstaats der EuropĂ€ischen Union, in dem der Lizenzgeber seinen Sitz, Wohnsitz oder eingetragenen Sitz hat; â diese Lizenz unterliegt dem belgischen Recht, wenn der Lizenzgeber keinen Sitz, Wohnsitz oder eingetragenen Sitz in einem Mitgliedstaat der EuropĂ€ischen Union hat. Anlage âKompatible Lizenzenâ nach Artikel 5 der EUPL sind: â GNU General Public License (GPL) v. 2, v. 3 â GNU Affero General Public License (AGPL) v. 3 â Open Software License (OSL) v. 2.1, v. 3.0 â Eclipse Public License (EPL) v. 1.0 â CeCILL v. 2.0, v. 2.1 â Mozilla Public Licence (MPL) v. 2 â GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 â Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) fĂŒr andere Werke als Software â European Union Public Licence (EUPL) v. 1.1, v. 1.2 â QuĂ©bec Free and Open-Source Licence â Reciprocity (LiLiQ-R) oder Strong Reciprocity (LiLiQ-R+) Die EuropĂ€ische Kommission kann diesen Anhang aktualisieren, um neuere Fassungen der obigen Lizenzen aufzunehmen, ohne hierfĂŒr eine neue Fassung der EUPL auszuarbeiten, solange diese Lizenzen die in Artikel 2 gewĂ€hrten Rechte gewĂ€hrleisten und den erfassten Quellcode vor ausschlieĂlicher Aneignung schĂŒtzen. Alle sonstigen Ănderungen oder ErgĂ€nzungen dieses Anhangs bedĂŒrfen der Ausarbeitung einer neuen Version der EUPL. |
Added license.en version [fc940c93f2].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016 This European Union Public Licence (the âEUPLâ) applies to the Work (as defined below) which is provided under the terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such use is covered by a right of the copyright holder of the Work). The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following notice immediately following the copyright notice for the Work: Licensed under the EUPL or has expressed by any other means his willingness to license under the EUPL. 1. Definitions In this Licence, the following terms have the following meaning: - âThe Licenceâ: this Licence. - âThe Original Workâ: the work or software distributed or communicated by the Licensor under this Licence, available as Source Code and also as Executable Code as the case may be. - âDerivative Worksâ: the works or software that could be created by the Licensee, based upon the Original Work or modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in the country mentioned in Article 15. - âThe Workâ: the Original Work or its Derivative Works. - âThe Source Codeâ: the human-readable form of the Work which is the most convenient for people to study and modify. - âThe Executable Codeâ: any code which has generally been compiled and which is meant to be interpreted by a computer as a program. - âThe Licensorâ: the natural or legal person that distributes or communicates the Work under the Licence. - âContributor(s)â: any natural or legal person who modifies the Work under the Licence, or otherwise contributes to the creation of a Derivative Work. - âThe Licenseeâ or âYouâ: any natural or legal person who makes any usage of the Work under the terms of the Licence. - âDistributionâ or âCommunicationâ: any act of selling, giving, lending, renting, distributing, communicating, transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential functionalities at the disposal of any other natural or legal person. 2. Scope of the rights granted by the Licence The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for the duration of copyright vested in the Original Work: - use the Work in any circumstance and for all usage, - reproduce the Work, - modify the Work, and make Derivative Works based upon the Work, - communicate to the public, including the right to make available or display the Work or copies thereof to the public and perform publicly, as the case may be, the Work, - distribute the Work or copies thereof, - lend and rent the Work or copies thereof, - sublicense rights in the Work or copies thereof. Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the applicable law permits so. In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed by law in order to make effective the licence of the economic rights here above listed. The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the extent necessary to make use of the rights granted on the Work under this Licence. 3. Communication of the Source Code The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to distribute or communicate the Work. 4. Limitations on copyright Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations thereto. 5. Obligations of the Licensee The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those obligations are the following: Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work to carry prominent notices stating that the Work has been modified and the date of modification. Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless the Original Work is expressly distributed only under this version of the Licence â for example by communicating âEUPL v. 1.2 onlyâ. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the Work or Derivative Work that alter or restrict the terms of the Licence. Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done under the terms of this Compatible Licence. For the sake of this clause, âCompatible Licenceâ refers to the licences listed in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail. Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available for as long as the Licensee continues to distribute or communicate the Work. Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the copyright notice. 6. Chain of Authorship The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence. Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or licensed to him/her and that he/she has the power and authority to grant the Licence. Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions to the Work, under the terms of this Licence. 7. Disclaimer of Warranty The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work and may therefore contain defects or âbugsâ inherent to this type of development. For the above reason, the Work is provided under the Licence on an âas isâ basis and without warranties of any kind concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this Licence. This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work. 8. Disclaimer of Liability Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However, the Licensor will be liable under statutory product liability laws as far such laws apply to the Work. 9. Additional agreements While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by the fact You have accepted any warranty or additional liability. 10. Acceptance of the Licence The provisions of this Licence can be accepted by clicking on an icon âI agreeâ placed under the bottom of a window displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms and conditions. Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution or Communication by You of the Work or copies thereof. 11. Information to the public In case of any Distribution or Communication of the Work by means of electronic communication by You (for example, by offering to download the Work from a remote location) the distribution channel or media (for example, a website) must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence and the way it may be accessible, concluded, stored and reproduced by the Licensee. 12. Termination of the Licence The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms of the Licence. Such a termination will not terminate the licences of any person who has received the Work from the Licensee under the Licence, provided such persons remain in full compliance with the Licence. 13. Miscellaneous Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the Work. If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid and enforceable. The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence. New versions of the Licence will be published with a unique version number. All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take advantage of the linguistic version of their choice. 14. Jurisdiction Without prejudice to specific agreement between parties, - any litigation resulting from the interpretation of this License, arising between the European Union institutions, bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union, - any litigation arising between other parties and resulting from the interpretation of this License, will be subject to the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business. 15. Applicable Law Without prejudice to specific agreement between parties, - this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat, resides or has his registered office, - this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside a European Union Member State. Appendix âCompatible Licencesâ according to Article 5 EUPL are: - GNU General Public License (GPL) v. 2, v. 3 - GNU Affero General Public License (AGPL) v. 3 - Open Software License (OSL) v. 2.1, v. 3.0 - Eclipse Public License (EPL) v. 1.0 - CeCILL v. 2.0, v. 2.1 - Mozilla Public Licence (MPL) v. 2 - GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 - Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software - European Union Public Licence (EUPL) v. 1.1, v. 1.2 - QuĂ©bec Free and Open-Source Licence â Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+). The European Commission may update this Appendix to later versions of the above licences without producing a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the covered Source Code from exclusive appropriation. All other changes or additions to this Appendix require the production of a new EUPL version. |
Modified math.t from [fe958b6645] to [f642fd73ba].
78 79 80 81 82 83 84 85 86 |
for i = 0, len do var v, ok = m.shorthand.cval(s[i]) if ok == false then return 0, false end val = (val * 64) + v end return val, true end return m |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 |
for i = 0, len do var v, ok = m.shorthand.cval(s[i]) if ok == false then return 0, false end val = (val * 64) + v end return val, true end terra m.hexdigit(hb: uint8): int8 var a = hb and 0x0F if a < 10 then return 0x30 + a else return 0x61 + (a-10) end end terra m.hexbyte(b: uint8): int8[2] return array(m.hexdigit((b and 0xF0) >> 4), m.hexdigit(b and 0x0F)) end terra m.hexstr(src: &uint8, str: rawstring, sz: intptr) for i = 0, sz do var d = m.hexbyte(src[i]) str[i*2] = d[0] str[i*2 + 1] = d[1] end end terra m.b32char(v: uint8): int8 if v <= 25 then return 0x61 + v elseif v < 31 then return 0x32 + (v-26) else return 0 end end terra m.b32(v: uint64, buf: rawstring) -- 5 bytes -> 8 chars while v > 0 do var val = v % 32 v = v / 32 @buf = m.b32char(val) buf = buf + 1 end end terra m.b32str(a: lib.mem.ptr(uint64)) end return m |
Added mem.t version [07d2cb4a7e].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 |
-- vim: ft=terra local m = { zero = macro(function(r) return quote for i = 0, [r.tree.type.N] do r[i] = 0 end end end); heapa_raw = terralib.externfunction('malloc', intptr -> &opaque); heapr_raw = terralib.externfunction('realloc', {&opaque, intptr} -> &opaque); heapf = terralib.externfunction('free', &opaque -> {}); cpy = terralib.externfunction('mempcpy',{&opaque, &opaque, intptr} -> &opaque); } m.heapa = macro(function(ty, sz) local p = m.ptr(ty:astype()) return `p { ptr = [&ty:astype()](m.heapa_raw(sizeof(ty) * sz)); ct = sz; } end) m.ptr = terralib.memoize(function(ty) local t = terralib.types.newstruct(string.format('ptr<%s>', ty)) t.entries = { {'ptr', &ty}; {'ct', intptr}; } t.ptr_basetype = ty local recurse = false if ty:isstruct() then if ty.methods.free then recurse = true end end t.metamethods.__not = macro(function(self) return `self.ptr end) t.methods = { free = terra(self: &t): bool [recurse and quote self.ptr:free() end or {}] if self.ct > 0 then m.heapf(self.ptr) self.ct = 0 return true end return false end; init = terra(self: &t, newct: intptr): bool var nv = [&ty](m.heapa_raw(sizeof(ty) * newct)) if nv ~= nil then self.ptr = nv self.ct = newct return true else return false end end; resize = terra(self: &t, newct: intptr): bool var nv: &ty if self.ct > 0 then nv = [&ty](m.heapr_raw(self.ptr, sizeof(ty) * newct)) else nv = [&ty](m.heapa_raw(sizeof(ty) * newct)) end if nv ~= nil then self.ptr = nv self.ct = newct return true else return false end end; } return t end) m.vec = terralib.memoize(function(ty) local v = terralib.types.newstruct(string.format('vec<%s>', ty.name)) v.entries = { {field = 'storage', type = m.ptr(ty)}; {field = 'sz', type = intptr}; {field = 'run', type = intptr}; } local terra biggest(a: intptr, b: intptr) if a > b then return a else return b end end terra v:assure(n: intptr) if self.storage.ct < n then self.storage:resize(biggest(n, self.storage.ct + self.run)) end end v.methods = { init = terra(self: &v, run: intptr): bool if not self.storage:init(run) then return false end self.run = run self.sz = 0 return true end; new = terra(self: &v): &ty self:assure(self.sz + 1) self.sz = self.sz + 1 return self.storage.ptr + (self.sz - 1) end; push = terra(self: &v, val: ty) self:assure(self.sz + 1) self.storage.ptr[self.sz] = val self.sz = self.sz + 1 end; free = terra(self: &v) self.storage:free() end; last = terra(self: &v, idx: intptr): &ty if self.sz > idx then return self.storage.ptr + (self.sz - (idx+1)) else lib.bail('vector underrun!') end end; crush = terra(self: &v) self.storage:resize(self.sz) return self.storage end; } v.metamethods.__apply = terra(self: &v, idx: intptr): &ty -- no index?? if self.sz > idx then return self.storage.ptr + idx else lib.bail('vector overrun!') end end return v end) return m |
Modified parsav.md from [d4a5d691bd] to [93a3706cc3].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# parsav **parsav** is a lightweight fediverse server ## dependencies * libhttp * json-c * mbedtls * postgresql-libs ## building first, either install any missing dependencies as shared libraries, or build them as static libraries as described below: * libhttp: run `$ make lib/libhttp/lib/libhttp.a` * json-c (deps: `cmake`): run `$ make lib/json-c/libjson-c.a` * mbedtls: run `$ make lib/mbedtls/lib/mbed{crypto,tls,x509}.a` you can install static libraries for all dependencies with `$ make dep`, but this is recommended only if you have none of the above |
> > > > > < > > | | < < < > < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 |
# parsav **parsav** is a lightweight fediverse server ## backends parsav is designed to be storage-agnostic, and can draw data from multiple backends at a time. backends can be enabled or disabled at compile time to avoid unnecessary dependencies. * postgresql ## dependencies * mongoose * json-c * mbedtls * **postgresql backend:** * postgresql-libs ## building first, either install any missing dependencies as shared libraries, or build them as static libraries with the command `make dep.$LIBRARY`. as a shortcut, `make dep` will build all dependencies as static libraries. note that if the build system finds a static version of a librari in the `lib/` folder, it will use that instead of any system library. postgresql-libs must be installed systemwide, as `parsav` does not currently provide for statically compiling and linking it ## configuring the `parsav` configuration is comprised of two components: the backends list and the config store. the backends list is a simple text file that tells `parsav` which data sources to draw from. the config store is a key-value store which contains the rest of the server's configuration, and is loaded from the backends. the configuration store can be spread across the backends; backends will be checked for configuration keys according to the order in which they are listed. changes to the configuration store affect parsav in real time; you only need to restart the server if you make a change to the backend list. eventually, we'll add a command-line tool `parsav-cfg` to enable easy modification of the configuration store from the command line; for now, you'll need to modify the database by hand or use the online administration menu. the schema.sql file contains commands to prompt for various important values like the name of your administrative user. by default, parsav looks for a file called `backend.conf` in the current directory when it is launched. you can override this default with the `parsav_backend_file` environment or with the `-b`/`--backend-file` flag. `backend.conf` lists one backend per line, in the form `id type confstring`. for instance, if you had two postgresql databases, you might write a backend file like master pgsql host=localhost dbname=parsav tweets pgsql host=420.69.dread.cloud dbname=content the form the configuration string takes depends on the specific backend. ### postgresql backend currently, postgres needs to be configured manually before parsav can make use of it to store data. the first step is to create a database for parsav's use. once you've done that, you need to create the database schema with the command `$ psql (-h $host) -d $database -f schema.sql`. you'll be prompted for some crucial settings to install in the configuration store, such as the name of the relation you want to use for authentication (we'll call it `parsav_auth` from here on out). parsav separates the storage of user credentials from the storage of other user data, in order to facilitate centralized user accounting. you don't need to take advantage of this feature, and if you don't want to, you can just create a `parsav_auth` table and have done. however, `parsav_auth` can also be a view, collecting a list of authorized users and their various credentials from whatever source you please. `parsav_auth` has the following schema: create table parsav_auth ( aid bigint primary key, uid bigint, newname text, kind text not null, cred bytea not null, restrict text[], netmask cidr, blacklist bool ) `aid` is a unique value identifying the authentication method. it must be deterministic -- values based on time of creation or a hash of `uid`+`kind`+`cred` are ideal. `uid` is the identifier of the user the row specifies credentials for. `kind` is a string indicating the credential type, and `cred` is the content of that credential.for the meaning of these fields and use of this structure, see **authentication** below. ## authentication in the most basic case, an authentication record would be something like `{uid = 123, kind = "pw-sha512", cred = "12bf90âŠa10e"}`. but `parsav` is not restricted to username-password authentication, and in addition to various hashing styles, it also will support more esoteric forms of authentcation. any individual user can have as many auth rows as she likes. there is also a `restrict` field, which is normally null, but can be specified in order to restrict a particular credential to certain operations, such as posting tweets or updating a bio. `blacklist` indicates that any attempt to authenticate that matches this row will be denied, regardless of whether it matches other rows. if `netmask` is present, this authentication will only succeed if it comes from the specified IP mask. `uid` can also be `0` (not null, which matches any user!), indicating that there is not yet a record in `parsav_actors` for this account. if this is the case, `name` must contain the handle of the account to be created when someone attempts to log in with this credential. whether `name` is used in the authentication process depends on whether the authentication method accepts a username. all rows with the same `uid` *must* have the same `name`. below is a full list of authentication types we intend to support. a checked box indicates the scheme has been implemented. * â pw-sha{512,384,256,224}: an ordinary password, hashed with the appropriate algorithm * â pw-{sha1,md5,clear} (insecure, must be manually enabled at compile time with the config variable `parsav_let_me_be_a_dumbass="i know what i'm doing"`) * â pw-pbkdf2-hmac-sha{âŠ}: a password hashed with the Password-Based Key Derivation Function 2 instead of plain SHA2 * â api-digest-sha{âŠ}: a value that can be hashed with the current epoch to derive a temporary access key without logging in. these are used for API calls, sent in the header `X-API-Key`. * â otp-time-sha1: a TOTP PSK: the first two bytes represent the step, the third byte the OTP length, and the remaining ten bytes the secret key * â tls-cert-fp: a fingerprint of a client certificate * â tls-cert-ca: a value of the form `fp/key=value` where a client certificate with the property `key=value` (e.g. `uid=cyberlord19`) signed by a certificate authority matching the given fingerprint `fp` can authenticate the user * â challenge-rsa-sha256: an RSA public key. the user is presented with a challenge and must sign it with the corresponding private key using SHA256. * â challenge-ecc-sha256: a Curve25519 public key. the user is presented with a challenge and must sign it with the corresponding private key using SHA256. * â challenge-ecc448-sha256: a Curve448 public key. the user is presented with a challenge and must sign it with the corresponding private key using SHA256. * â trust: authentication always succeeds. only use in combination with netmask!!! ## license parsav is released under the terms of the EUPL v1.2. copies of this license are included in the repository. dependencies are produced ## future direction parsav needs more storage backends, as it currently supports only postgres. some possibilities, in order of priority, are: * plain text/filesystem storage * lmdb * sqlite3 * generic odbc * lua * ldap?? possibly just for users * cdb (for static content, maybe?) * mariadb/mysql * the various nosql horrors, e.g. redis, mongo, and so on |
Modified parsav.t from [ce122c09dc] to [fcc06cebed].
2 3 4 5 6 7 8 9 10 11 12 13 14 15 .. 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 .. 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 ... 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 ... 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 ... 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 ... 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
local util = dofile('common.lua')
local buildopts, buildargs = util.parseargs{...}
config = dofile('config.lua')
lib = {
init = {};
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
return terralib.includec(p.incdir .. '/' .. hdr)
end;
................................................................................
return macro(function(v,...)
for ty,fn in pairs(tbl) do
if v.tree.type == ty then return fn(v,...) end
end
return (tbl[false])(v,...)
end)
end;
emit = function(...)
local code = {}
for i,v in ipairs{...} do
if type(v) == 'string' or type(v) == 'number' then
local str = tostring(v)
code[#code+1] = `lib.io.send(2, str, [#str])
elseif v.tree:is 'constant' then
local str = tostring(v:asvalue())
code[#code+1] = `lib.io.send(2, str, [#str])
else
code[#code+1] = quote var n = v in
lib.io.send(2, n, lib.str.sz(n)) end
end
end
code[#code+1] = `lib.io.send(2, '\n', 1)
return code
end;
trn = macro(function(cond, i, e)
return quote
var c: bool = [cond]
var r: i.tree.type
if c == true then r = i else r = e end
in r end
end);
................................................................................
io = {
send = terralib.externfunction('write', {int, rawstring, intptr} -> ptrdiff);
recv = terralib.externfunction('read', {int, rawstring, intptr} -> ptrdiff);
say = macro(function(msg) return `lib.io.send(2, msg, [#(msg:asvalue())]) end);
fmt = terralib.externfunction('printf',
terralib.types.funcpointer({rawstring},{int},true));
};
str = {
sz = terralib.externfunction('strlen', rawstring -> intptr);
cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int);
ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int);
cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring);
ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring);
ndup = terralib.externfunction('strndup',{rawstring, intptr} -> rawstring);
fmt = terralib.externfunction('asprintf',
terralib.types.funcpointer({&rawstring},{int},true));
};
copy = function(tbl)
local new = {}
for k,v in pairs(tbl) do new[k] = v end
setmetatable(new, getmetatable(tbl))
return new
end;
mem = {
zero = macro(function(r)
return quote
for i = 0, [r.tree.type.N] do r[i] = 0 end
end
end);
heapa_raw = terralib.externfunction('malloc', intptr -> &opaque);
heapr_raw = terralib.externfunction('realloc', {&opaque, intptr} -> &opaque);
heapf = terralib.externfunction('free', &opaque -> {});
cpy = terralib.externfunction('mempcpy',{&opaque, &opaque, intptr} -> &opaque);
heapa = macro(function(ty, sz)
local p = lib.mem.ptr(ty:astype())
return `p {
ptr = [&ty:astype()](lib.mem.heapa_raw(sizeof(ty) * sz));
ct = sz;
}
end)
};
}
local noise = global(uint8,1)
local noise_header = function(code,txt,mod)
if mod then
return string.format('\27[%s;1m(parsav::%s %s)\27[m ', code,mod,txt)
else
return string.format('\27[%s;1m(parsav %s)\27[m ', code,txt)
end
end
local defrep = function(level,n,code)
return macro(function(...)
local q = lib.emit(noise_header(code,n), ...)
return quote
if noise >= level then [q] end
end
end);
end
lib.dbg = defrep(3,'debug', '32')
lib.report = defrep(2,'info', '35')
lib.warn = defrep(1,'warn', '33')
lib.bail = macro(function(...)
local q = lib.emit(noise_header('31','fatal'), ...)
return quote
[q]
lib.proc.exit(1)
end
end);
lib.stat = terralib.memoize(function(ty)
local n = struct {
................................................................................
elseif #tbl >= 2^8 then ty = uint16 end
local o = { t = ty }
for i, name in ipairs(tbl) do
o[name] = i
end
return o
end
lib.mem.ptr = terralib.memoize(function(ty)
local t = terralib.types.newstruct(string.format('ptr<%s>', ty))
t.entries = {
{'ptr', &ty};
{'ct', intptr};
}
t.ptr_basetype = ty
local recurse = false
if ty:isstruct() then
if ty.methods.free then recurse = true end
end
t.methods = {
free = terra(self: &t): bool
[recurse and quote
self.ptr:free()
end or {}]
if self.ct > 0 then
lib.mem.heapf(self.ptr)
self.ct = 0
return true
end
return false
end;
init = terra(self: &t, newct: intptr): bool
var nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
resize = terra(self: &t, newct: intptr): bool
var nv: &ty
if self.ct > 0
then nv = [&ty](lib.mem.heapr_raw(self.ptr, sizeof(ty) * newct))
else nv = [&ty](lib.mem.heapa_raw(sizeof(ty) * newct))
end
if nv ~= nil then
self.ptr = nv
self.ct = newct
return true
else return false end
end;
}
return t
end)
lib.mem.vec = terralib.memoize(function(ty)
local v = terralib.types.newstruct(string.format('vec<%s>', ty.name))
v.entries = {
{field = 'storage', type = lib.mem.ptr(ty)};
{field = 'sz', type = intptr};
{field = 'run', type = intptr};
}
local terra biggest(a: intptr, b: intptr)
if a > b then return a else return b end
end
terra v:assure(n: intptr)
if self.storage.ct < n then
self.storage:resize(biggest(n, self.storage.ct + self.run))
end
end
v.methods = {
init = terra(self: &v, run: intptr): bool
if not self.storage:init(run) then return false end
self.run = run
self.sz = 0
return true
end;
new = terra(self: &v): &ty
self:assure(self.sz + 1)
self.sz = self.sz + 1
return self.storage.ptr + (self.sz - 1)
end;
push = terra(self: &v, val: ty)
self:assure(self.sz + 1)
self.storage.ptr[self.sz] = val
self.sz = self.sz + 1
end;
free = terra(self: &v) self.storage:free() end;
last = terra(self: &v, idx: intptr): &ty
if self.sz > idx then
return self.storage.ptr + (self.sz - (idx+1))
else lib.bail('vector underrun!') end
end;
crush = terra(self: &v)
self.storage:resize(self.sz)
return self.storage
end;
}
v.metamethods.__apply = terra(self: &v, idx: intptr): &ty -- no index??
if self.sz > idx then
return self.storage.ptr + idx
else lib.bail('vector overrun!') end
end
return v
end)
lib.err = lib.loadlib('mbedtls','mbedtls/error.h')
lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h')
lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h')
lib.md = lib.loadlib('mbedtls','mbedtls/md.h')
lib.b64 = lib.loadlib('mbedtls','mbedtls/base64.h')
lib.net = lib.loadlib('mongoose','mongoose.h')
lib.pq = lib.loadlib('libpq','libpq-fe.h')
lib.file = terralib.loadfile('file.t')()
lib.math = terralib.loadfile('math.t')()
lib.crypt = terralib.loadfile('crypt.t')()
lib.http = terralib.loadfile('http.t')()
lib.tpl = terralib.loadfile('tpl.t')()
lib.string = terralib.loadfile('string.t')()
lib.store = terralib.loadfile('store.t')()
local be = {}
for _, b in pairs { 'pgsql' } do
be[#be+1] = terralib.loadfile('backend/' .. b .. '.t')()
end
lib.store.backends = global(`array([be]))
lib.cmdparse = terralib.loadfile('cmdparse.t')()
lib.srv = terralib.loadfile('srv.t')()
................................................................................
local pemdump = macro(function(pub, kp)
local msg = (pub:asvalue() and ' * emitting public key\n') or ' * emitting private key\n'
return quote
var buf: lib.crypt.pemfile
lib.mem.zero(buf)
lib.crypt.pem(pub, &kp, buf)
lib.io.send(1, msg, [#msg])
lib.io.send(1, [rawstring](&buf), lib.str.sz([rawstring](&buf)))
lib.io.send(1, '\n', 1)
end
end)
do
local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
terra version() lib.io.send(1, p, [#p]) end
end
................................................................................
end
noise = 1
end
local options = lib.cmdparse {
version = {'V', 'display information about the binary build and exit'};
quiet = {'q', 'do not print to standard out'};
help = {'h', 'display this list'}
}
terra entry(argc: int, argv: &rawstring): int
noise_init()
[lib.init]
-- shut mongoose the fuck up
lib.net.mg_log_set_callback([terra(msg: &opaque, sz: int, u: &opaque) end], nil)
var mode: options
mode:parse(argc,argv)
if mode.version then
version()
return 0
end
if mode.help then
lib.io.send(1, [options.helptxt], [#options.helptxt])
return 0
end
var srv: lib.srv
srv:start('backend.conf')
lib.report('listening for requests')
while true do
srv:poll()
end
srv:shutdown()
return 0
................................................................................
end
if bflag('dump-config','C') then
print(util.dump(config))
os.exit(0)
end
local emit = print
if bflag('quiet','q') then emit = function() end end
local out = config.exe and 'parsav' or 'parsav.o'
local linkargs = {}
if config.posix then
linkargs[#linkargs+1] = '-pthread'
end
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
emit('linking with args',util.dump(linkargs))
terralib.saveobj(out, {
main = entry
},
linkargs,
config.tgttrip and terralib.newtarget {
Triple = config.tgttrip;
CPU = config.tgtcpu;
FloatABIHard = config.tgthf;
} or nil)
|
> > > > > | > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < < < < < < < < < < < < < < < < < < < < < < < | < < < > > > > | | | | | | | < > | | | | > > | < < > > > | < < < < > | | | < | < < < < < < < | < < < < < | < < < < < < < | | < < < < < < < < < > > > > > > | < < < > | < < < < < > > > > > > > | | < < < < < < < < < < < < < < < < > | < < > > > > > > | < < < < < | | < > | | | < < < | > | > | | | | > > > > | | | < < < | | | | > > | > > > > > > | > > | < < > > > > > | |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 .. 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 .. 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 ... 152 153 154 155 156 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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 ... 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 ... 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 ... 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
local util = dofile('common.lua')
local buildopts, buildargs = util.parseargs{...}
config = dofile('config.lua')
lib = {
init = {};
load = function(lst)
for _, l in pairs(lst) do
lib[l] = terralib.loadfile(l .. '.t')()
end
end;
loadlib = function(name,hdr)
local p = config.pkg[name]
-- for _,v in pairs(p.dylibs) do
-- terralib.linklibrary(p.libdir .. '/' .. v)
-- end
return terralib.includec(p.incdir .. '/' .. hdr)
end;
................................................................................
return macro(function(v,...)
for ty,fn in pairs(tbl) do
if v.tree.type == ty then return fn(v,...) end
end
return (tbl[false])(v,...)
end)
end;
emit_unitary = function(fd,...)
local code = {}
for i,v in ipairs{...} do
if type(v) == 'string' or type(v) == 'number' then
local str = tostring(v)
code[#code+1] = `lib.io.send(2, str, [#str])
elseif type(v) == 'table' and #v == 2 then
code[#code+1] = `lib.io.send(2, [v[1]], [v[2]])
elseif v.tree:is 'constant' then
local str = tostring(v:asvalue())
code[#code+1] = `lib.io.send(2, str, [#str])
else
code[#code+1] = quote var n = v in
lib.io.send(2, n, lib.str.sz(n)) end
end
end
code[#code+1] = `lib.io.send(fd, '\n', 1)
return code
end;
emitv = function(fd,...)
local vec = {}
local defs = {}
for i,v in ipairs{...} do
local str, ct
if type(v) == 'table' and v.tree and not (v.tree:is 'constant') then
if v.tree.type.convertible == 'tuple' then
str = `v._0
ct = `v._1
else
local n = symbol(v.tree.type)
defs[#defs + 1] = quote var [n] = v end
str = n
ct = `lib.str.sz(n)
end
else
if type(v) == 'string' or type(v) == 'number' then
str = tostring(v)
else--if v.tree:is 'constant' then
str = tostring(v:asvalue())
end
ct = ct or #str
end
vec[#vec + 1] = `[lib.uio.iovec]{iov_base = [&opaque](str), iov_len = ct}
end
vec[#vec + 1] = `[lib.uio.iovec]{iov_base = [&opaque]('\n'), iov_len = 1}
return quote
[defs]
var strs = array( [vec] )
in lib.uio.writev(fd, strs, [#vec]) end
end;
trn = macro(function(cond, i, e)
return quote
var c: bool = [cond]
var r: i.tree.type
if c == true then r = i else r = e end
in r end
end);
................................................................................
io = {
send = terralib.externfunction('write', {int, rawstring, intptr} -> ptrdiff);
recv = terralib.externfunction('read', {int, rawstring, intptr} -> ptrdiff);
say = macro(function(msg) return `lib.io.send(2, msg, [#(msg:asvalue())]) end);
fmt = terralib.externfunction('printf',
terralib.types.funcpointer({rawstring},{int},true));
};
str = { sz = terralib.externfunction('strlen', rawstring -> intptr) };
copy = function(tbl)
local new = {}
for k,v in pairs(tbl) do new[k] = v end
setmetatable(new, getmetatable(tbl))
return new
end;
}
if config.posix then
lib.uio = terralib.includec 'sys/uio.h';
lib.emit = lib.emitv -- use more efficient call where available
else lib.emit = lib.emit_unitary end
local noise = global(uint8,1)
local noise_header = function(code,txt,mod)
if mod then
return string.format('\27[%s;1m(parsav::%s %s)\27[m ', code,mod,txt)
else
return string.format('\27[%s;1m(parsav %s)\27[m ', code,txt)
end
end
local defrep = function(level,n,code)
return macro(function(...)
local q = lib.emit(2, noise_header(code,n), ...)
return quote
if noise >= level then [q] end
end
end);
end
lib.dbg = defrep(3,'debug', '32')
lib.report = defrep(2,'info', '35')
lib.warn = defrep(1,'warn', '33')
lib.bail = macro(function(...)
local q = lib.emit(2, noise_header('31','fatal'), ...)
return quote
[q]
lib.proc.exit(1)
end
end);
lib.stat = terralib.memoize(function(ty)
local n = struct {
................................................................................
elseif #tbl >= 2^8 then ty = uint16 end
local o = { t = ty }
for i, name in ipairs(tbl) do
o[name] = i
end
return o
end
lib.set = function(tbl)
local bytes = math.ceil(#tbl / 8)
local o = {}
for i, name in ipairs(tbl) do o[name] = i end
local struct set { _store: uint8[bytes] }
local struct bit { _v: intptr _set: &set}
terra set:clear() for i=0,bytes do self._store[i] = 0 end end
set.members = tbl
set.name = string.format('set<%s>', table.concat(tbl, '|'))
set.metamethods.__entrymissing = macro(function(val, obj)
if o[val] == nil then error('value ' .. val .. ' not in set') end
return `bit { _v=[o[val] - 1], _set = &obj }
end)
set.methods.dump = macro(function(self)
local q = quote lib.io.say('dumping set:\n') end
for i,v in ipairs(tbl) do
q = quote
[q]
if [bool](self.[v])
then lib.io.say([' - ' .. v .. ': true\n'])
else lib.io.say([' - ' .. v .. ': false\n'])
end
end
end
return q
end)
set.metamethods.__add = macro(function(self,other)
local new = symbol(set)
local q = quote var [new] new:clear() end
for i = 0, bytes - 1 do
q = quote [q]
new._store[i] = self._store[i] or other._store[i]
end
end
return quote [q] in new end
end)
bit.metamethods.__cast = function(from,to,e)
local q = quote var s = e
in (s._set._store[s._v/8] and (1 << s._v % 8)) end
if to == bit then error('casting to bit is not meaningful')
elseif to == bool then return `([q] ~= 0)
elseif to:isintegral() then return q
elseif from == bit then error('cannot cast bit to ' .. tostring(to))
else return nil end
end
bit.metamethods.__apply = terra(self: &bit): bool return @self end
bit.metamethods.__lshift = terra(self: &bit, hl: bool)
var byte = self._v / 8
var bit = self._v % 8
if hl then
self._set._store[byte] = self._set._store[byte] or (1 << bit)
else
self._set._store[byte] = self._set._store[byte] and not (1 << bit)
end
end
return set
end
lib.err = lib.loadlib('mbedtls','mbedtls/error.h')
lib.rsa = lib.loadlib('mbedtls','mbedtls/rsa.h')
lib.pk = lib.loadlib('mbedtls','mbedtls/pk.h')
lib.md = lib.loadlib('mbedtls','mbedtls/md.h')
lib.b64 = lib.loadlib('mbedtls','mbedtls/base64.h')
lib.net = lib.loadlib('mongoose','mongoose.h')
lib.pq = lib.loadlib('libpq','libpq-fe.h')
lib.load {
'mem', 'str', 'file', 'math', 'crypt';
'http', 'tpl', 'store';
}
local be = {}
for _, b in pairs(config.backends) do
be[#be+1] = terralib.loadfile('backend/' .. b .. '.t')()
end
lib.store.backends = global(`array([be]))
lib.cmdparse = terralib.loadfile('cmdparse.t')()
lib.srv = terralib.loadfile('srv.t')()
................................................................................
local pemdump = macro(function(pub, kp)
local msg = (pub:asvalue() and ' * emitting public key\n') or ' * emitting private key\n'
return quote
var buf: lib.crypt.pemfile
lib.mem.zero(buf)
lib.crypt.pem(pub, &kp, buf)
lib.emit(msg, buf, '\n')
--lib.io.send(1, msg, [#msg])
--lib.io.send(1, [rawstring](&buf), lib.str.sz([rawstring](&buf)))
--lib.io.send(1, '\n', 1)
end
end)
do
local p = string.format('parsav: %s\nbuilt on %s\n', config.build.str, config.build.when)
terra version() lib.io.send(1, p, [#p]) end
end
................................................................................
end
noise = 1
end
local options = lib.cmdparse {
version = {'V', 'display information about the binary build and exit'};
quiet = {'q', 'do not print to standard out'};
help = {'h', 'display this list'};
backend_file = {'b', 'init from specified backend file', 1};
}
terra entry(argc: int, argv: &rawstring): int
if argc < 1 then lib.bail('bad invocation!') end
noise_init()
[lib.init]
-- shut mongoose the fuck up
lib.net.mg_log_set_callback([terra(msg: &opaque, sz: int, u: &opaque) end], nil)
var srv: lib.srv
do var mode: options
mode:parse(argc,argv) defer mode:free()
if mode.version then version() return 0 end
if mode.help then
lib.io.send(1, [options.helptxt], [#options.helptxt])
return 0
end
var cnf: rawstring
if mode.backend_file ~= 0
then if mode.arglist.ct >= mode.backend_file
then cnf = mode.arglist.ptr[mode.backend_file - 1]
else lib.bail('bad invocation, backend file not specified') end
else cnf = lib.proc.getenv('parsav_backend_file')
end
if cnf == nil then cnf = "backend.conf" end
srv:start(cnf)
end
lib.report('listening for requests')
while true do
srv:poll()
end
srv:shutdown()
return 0
................................................................................
end
if bflag('dump-config','C') then
print(util.dump(config))
os.exit(0)
end
local holler = print
local out = config.exe and 'parsav' or 'parsav.o'
local linkargs = {}
if bflag('quiet','q') then holler = function() end end
if bflag('asan','s') then linkargs[#linkargs+1] = '-fsanitize=address' end
if bflag('lsan','S') then linkargs[#linkargs+1] = '-fsanitize=leak' end
if config.posix then
linkargs[#linkargs+1] = '-pthread'
end
for _,p in pairs(config.pkg) do util.append(linkargs, p.linkargs) end
holler('linking with args',util.dump(linkargs))
terralib.saveobj(out, {
main = entry
},
linkargs,
config.tgttrip and terralib.newtarget {
Triple = config.tgttrip;
CPU = config.tgtcpu;
FloatABIHard = config.tgthf;
} or nil)
|
Modified schema.sql from [2da83887bf] to [6d12737279].
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
value text
);
insert into parsav_config (key,value) values
('bind',:'bind'),
('domain',:'domain'),
('auth-source',:'auth'),
('administrator',:'admin');
-- note that valid ids should always > 0, as 0 is reserved for null
-- on the client side, vastly simplifying code
drop table if exists parsav_servers cascade;
create table parsav_servers (
id bigint primary key default (1+random()*(2^63-1))::bigint,
domain text not null,
|
| > > > |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
value text
);
insert into parsav_config (key,value) values
('bind',:'bind'),
('domain',:'domain'),
('auth-source',:'auth'),
('administrator',:'admin'),
('server-secret', encode(
digest(int8send((2^63 * (random()*2 - 1))::bigint),
'sha512'), 'base64'));
-- note that valid ids should always > 0, as 0 is reserved for null
-- on the client side, vastly simplifying code
drop table if exists parsav_servers cascade;
create table parsav_servers (
id bigint primary key default (1+random()*(2^63-1))::bigint,
domain text not null,
|
Modified srv.t from [350801ad24] to [aed7239c9c].
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 .. 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 ... 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
var fr = lib.file.open(befile, [lib.file.mode.read])
if fr.ok == false then
lib.bail('could not open configuration file ', befile)
end
var f = fr.val
var c: lib.mem.vec(lib.store.source) c:init(8)
var text: lib.string.acc text:init(64)
do var buf: int8[64]
while true do
var ct = f:read(buf, [buf.type.N])
if ct == 0 then break end
text:push(buf, ct)
end
end
................................................................................
s.sources = c:crush()
end
--srv.methods.conf_set = terra(self: &srv, key: rawstring, val:rawstring)
-- self.sources.ptr[0]:conf_set(key, val)
--end
srv.metamethods.__methodmissing = macro(function(meth, self, ...)
local primary, ptr, stat, simple = 0,1,2,3
local tk, rt = primary
local expr = {...}
for _,f in pairs(lib.store.backend.entries) do
local fn = f.field or f[1]
local ft = f.type or f[2]
if fn == meth then
rt = ft.type.returntype
if rt == bool then tk = simple
elseif rt.stat_basetype then tk = stat
elseif rt.ptr_basetype then tk = ptr end
break
end
end
if tk == primary then
................................................................................
return `self.sources.ptr[0]:[meth]([expr])
else local ok, empty
local r = symbol(rt)
if tk == ptr then
ok = `r.ptr ~= nil
empty = `[rt]{ptr=nil,ct=0}
elseif tk == stat then
ok = `r.ok ~= false
empty = `[rt]{ok=false,error=1}
elseif tk == simple then
ok = `r == true
empty = `false
end
return quote
var [r] = empty
for i=0,self.sources.ct do var src = self.sources.ptr + i
if src.handle ~= nil then
r = src:[meth]([expr])
if [ok] then break
................................................................................
elseif dbbind.ptr ~= nil then
bind = dbbind.ptr
else bind = '[::]:10917' end
lib.report('binding to ', bind)
lib.net.mg_mgr_init(&self.webmgr)
self.webcon = lib.net.mg_http_listen(&self.webmgr, bind, handle.http, nil)
dbbind:free()
end
srv.methods.poll = terra(self: &srv)
lib.net.mg_mgr_poll(&self.webmgr,1000)
end
srv.methods.shutdown = terra(self: &srv)
|
| > > > > > > > > | > | > > > < > > |
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 .. 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 ... 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
var fr = lib.file.open(befile, [lib.file.mode.read])
if fr.ok == false then
lib.bail('could not open configuration file ', befile)
end
var f = fr.val
var c: lib.mem.vec(lib.store.source) c:init(8)
var text: lib.str.acc text:init(64)
do var buf: int8[64]
while true do
var ct = f:read(buf, [buf.type.N])
if ct == 0 then break end
text:push(buf, ct)
end
end
................................................................................
s.sources = c:crush()
end
--srv.methods.conf_set = terra(self: &srv, key: rawstring, val:rawstring)
-- self.sources.ptr[0]:conf_set(key, val)
--end
terra srv:actor_auth_how(ip: lib.store.inet, usn: rawstring)
var cs: lib.store.credset cs:clear()
for i=0,self.sources.ct do
var set: lib.store.credset = self.sources.ptr[i]:actor_auth_how(ip, usn)
cs = cs + set
end
return cs
end
srv.metamethods.__methodmissing = macro(function(meth, self, ...)
local primary, ptr, stat, simple, oid = 0,1,2,3,4
local tk, rt = primary
local expr = {...}
for _,f in pairs(lib.store.backend.entries) do
local fn = f.field or f[1]
local ft = f.type or f[2]
if fn == meth then
rt = ft.type.returntype
if rt == bool then tk = simple
elseif rt.type == 'integer' then tk = oid
elseif rt.stat_basetype then tk = stat
elseif rt.ptr_basetype then tk = ptr end
break
end
end
if tk == primary then
................................................................................
return `self.sources.ptr[0]:[meth]([expr])
else local ok, empty
local r = symbol(rt)
if tk == ptr then
ok = `r.ptr ~= nil
empty = `[rt]{ptr=nil,ct=0}
elseif tk == stat then
ok = `r.ok == true
empty = `[rt]{ok=false,error=1}
elseif tk == simple then
ok = `r == true
empty = `false
elseif tk == oid then
ok = `r ~= 0
empty = `0
end
return quote
var [r] = empty
for i=0,self.sources.ct do var src = self.sources.ptr + i
if src.handle ~= nil then
r = src:[meth]([expr])
if [ok] then break
................................................................................
elseif dbbind.ptr ~= nil then
bind = dbbind.ptr
else bind = '[::]:10917' end
lib.report('binding to ', bind)
lib.net.mg_mgr_init(&self.webmgr)
self.webcon = lib.net.mg_http_listen(&self.webmgr, bind, handle.http, nil)
if dbbind.ptr ~= nil then dbbind:free() end
end
srv.methods.poll = terra(self: &srv)
lib.net.mg_mgr_poll(&self.webmgr,1000)
end
srv.methods.shutdown = terra(self: &srv)
|
Modified store.t from [ed1d490f12] to [2c2e954f5c].
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .. 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 ... 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 |
};
notiftype = lib.enum {
'mention', 'like', 'rt', 'react'
};
relation = lib.enum {
'follow', 'mute', 'block'
};
}
local str = lib.mem.ptr(int8)
str:complete()
struct m.source
struct m.rights {
rank: uint16 -- lower = more powerful except 0 = regular user
-- creating staff automatically assigns rank immediately below you
quota: uint32 -- # of allowed tweets per day; 0 = no limit
................................................................................
struct m.actor {
id: uint64
nym: str
handle: str
origin: uint64
bio: str
rights: m.rights
key: str
source: &m.source
}
terra m.actor:free()
self.nym:free()
self.handle:free()
self.bio:free()
self.key:free()
end
struct m.range {
time: bool
union {
from_time: m.timepoint
from_idx: uint64
}
................................................................................
kind: m.notiftype.t
when: uint64
union {
post: uint64
reaction: int8[8]
}
}
-- backends only handle content on the local server
struct m.backend { id: rawstring
open: &m.source -> &opaque
close: &m.source -> {}
conf_get: {&m.source, rawstring} -> lib.mem.ptr(int8)
conf_set: {&m.source, rawstring, rawstring} -> {}
conf_reset: {&m.source, rawstring} -> {}
actor_save: {&m.source, m.actor} -> bool
actor_create: {&m.source, m.actor} -> bool
actor_fetch_xid: {&m.source, rawstring} -> lib.stat(m.actor)
actor_fetch_uid: {&m.source, uint64} -> lib.stat(m.actor)
actor_notif_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.notif)
actor_auth: {&m.source, rawstring, rawstring} -> lib.stat(m.actor)
actor_enum: {&m.source} -> lib.mem.ptr(m.actor)
actor_enum_local: {&m.source} -> lib.mem.ptr(m.actor)
actor_conf_str: cnf(rawstring, lib.mem.ptr(int8))
actor_conf_int: cnf(intptr, lib.stat(intptr))
post_save: {&m.source, &m.post} -> bool
post_create: {&m.source, &m.post} -> bool
actor_post_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(m.post)
|
> > | | > | < > > | < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < | | > > > > > > > > > > > > > > > > > > > > > > |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 .. 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 ... 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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
};
notiftype = lib.enum {
'mention', 'like', 'rt', 'react'
};
relation = lib.enum {
'follow', 'mute', 'block'
};
credset = lib.set {
'pw', 'otp', 'challenge', 'trust'
};
}
local str = rawstring --lib.mem.ptr(int8)
struct m.source
struct m.rights {
rank: uint16 -- lower = more powerful except 0 = regular user
-- creating staff automatically assigns rank immediately below you
quota: uint32 -- # of allowed tweets per day; 0 = no limit
................................................................................
struct m.actor {
id: uint64
nym: str
handle: str
origin: uint64
bio: str
rights: m.rights
key: lib.mem.ptr(uint8)
xid: str
source: &m.source
}
struct m.range {
time: bool
union {
from_time: m.timepoint
from_idx: uint64
}
................................................................................
kind: m.notiftype.t
when: uint64
union {
post: uint64
reaction: int8[8]
}
}
struct m.inet {
pv: uint8 -- 0 = null, 4 = ipv4, 6 = ipv6
union {
v4: uint8[4]
v6: uint8[16]
}
union {
fixbits: uint8 -- for cidr
port: uint16 -- for origin
}
}
terra m.inet:cidr_str()
if self.pv == 4 then
var maxsz = 3*4 + 3 + 1
elseif self.pv == 6 then
var bits = 128
var bytes = bits / 8
var hexchs = bytes * 2
var segs = hexchs / 4
var seps = segs - 1
var maxsz = hexchs + seps + 1
else return nil end
end
struct m.auth {
aid: uint64
uid: uint64
aname: str
netmask: m.inet
restrict: lib.mem.ptr(rawstring)
blacklist: bool
}
-- backends only handle content on the local server
struct m.backend { id: rawstring
open: &m.source -> &opaque
close: &m.source -> {}
conf_get: {&m.source, rawstring} -> lib.mem.ptr(int8)
conf_set: {&m.source, rawstring, rawstring} -> {}
conf_reset: {&m.source, rawstring} -> {}
actor_save: {&m.source, m.actor} -> bool
actor_create: {&m.source, m.actor} -> bool
actor_fetch_xid: {&m.source, rawstring} -> lib.mem.ptr(m.actor)
actor_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.actor)
actor_notif_fetch_uid: {&m.source, uint64} -> lib.mem.ptr(m.notif)
actor_enum: {&m.source} -> lib.mem.ptr(&m.actor)
actor_enum_local: {&m.source} -> lib.mem.ptr(&m.actor)
actor_auth_how: {&m.source, m.inet, rawstring} -> m.credset
-- returns a set of auth method categories that are available for a
-- given user from a certain origin
-- origin: inet
-- handle: rawstring
actor_auth_otp: {&m.source, m.inet, rawstring, rawstring} -> uint64
actor_auth_pw: {&m.source, m.inet, rawstring, rawstring} -> uint64
-- handles password-based logins against hashed passwords
-- origin: inet
-- handle: rawstring
-- token: rawstring
actor_auth_tls: {&m.source, m.inet, rawstring} -> uint64
-- handles implicit authentication performed as part of an TLS connection
-- origin: inet
-- fingerprint: rawstring
actor_auth_api: {&m.source, m.inet, rawstring, rawstring} -> uint64
-- handles API authentication
-- origin: inet
-- handle: rawstring
-- key: rawstring (X-API-Key)
actor_auth_record_fetch: {&m.source, uint64} -> lib.mem.ptr(m.auth)
actor_conf_str: cnf(rawstring, lib.mem.ptr(int8))
actor_conf_int: cnf(intptr, lib.stat(intptr))
post_save: {&m.source, &m.post} -> bool
post_create: {&m.source, &m.post} -> bool
actor_post_fetch_uid: {&m.source, uint64, m.range} -> lib.mem.ptr(m.post)
|
Added str.t version [4b8724b0aa].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
-- vim: ft=terra -- string.t: string classes local m = { sz = terralib.externfunction('strlen', rawstring -> intptr); cmp = terralib.externfunction('strcmp', {rawstring, rawstring} -> int); ncmp = terralib.externfunction('strncmp', {rawstring, rawstring, intptr} -> int); cpy = terralib.externfunction('stpcpy',{rawstring, rawstring} -> rawstring); ncpy = terralib.externfunction('stpncpy',{rawstring, rawstring, intptr} -> rawstring); dup = terralib.externfunction('strdup',rawstring -> rawstring); ndup = terralib.externfunction('strndup',{rawstring, intptr} -> rawstring); fmt = terralib.externfunction('asprintf', terralib.types.funcpointer({&rawstring,rawstring},{int},true)); bfmt = terralib.externfunction('sprintf', terralib.types.funcpointer({rawstring,rawstring},{int},true)); } (lib.mem.ptr(int8)).metamethods.__cast = function(from,to,e) if from == &int8 then return `[lib.mem.ptr(int8)]{ptr = e, ct = m.sz(e)} elseif to == &int8 then return e.ptr end end struct m.acc { buf: rawstring sz: intptr run: intptr space: intptr } local terra biggest(a: intptr, b: intptr) if a > b then return a else return b end end terra m.acc:init(run: intptr) lib.dbg('initializing string accumulator') self.buf = [rawstring](lib.mem.heapa_raw(run)) self.run = run self.space = run self.sz = 0 return self end; terra m.acc:free() lib.dbg('freeing string accumulator') if self.buf ~= nil and self.space > 0 then lib.mem.heapf(self.buf) end end; terra m.acc:crush() lib.dbg('crushing string accumulator') self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz)) self.space = self.sz return self end; terra m.acc:finalize() lib.dbg('finalizing string accumulator') self:crush() var pt: lib.mem.ptr(int8) pt.ptr = self.buf pt.ct = self.sz self.buf = nil self.sz = 0 return pt end; terra m.acc:push(str: rawstring, len: intptr) var llen = len if str == nil then return self end if str[len - 1] == 0xA then llen = llen - 1 end -- don't display newlines in debug output lib.dbg('pushing "',{str,llen},'" onto accumulator') if self.buf == nil then self:init(self.run) end if len == 0 then len = m.sz(str) end if len >= self.space - self.sz then self.space = self.space + biggest(self.run,len + 1) self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space)) end lib.mem.cpy(self.buf + self.sz, str, len) self.sz = self.sz + len self.buf[self.sz] = 0 return self end; m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) return self end; m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) str:free() return self end; m.acc.methods.compose = macro(function(self, ...) local minlen = 0 local pstrs = {} for i,v in ipairs{...} do if type(v) == 'table' then local gl = 16 -- guess wildly if v.tree and v.tree.type.convertible == 'tuple' then pstrs[#pstrs+1] = {str = `v._0, len = `v._1} elseif v.asvalue and type(v:asvalue()) == 'string' then local str = v:asvalue() pstrs[#pstrs+1] = {str = str, len = #str} gl = #str + 1 elseif v.tree and v.tree.type.ptr_basetype == int8 then pstrs[#pstrs+1] = {str = `v.ptr, len = `v.ct} else pstrs[#pstrs+1] = {str = v, len = 0} end minlen = minlen + gl elseif type(v) == 'string' then pstrs[#pstrs+1] = {str = v, len = #v} minlen = minlen + #v + 1 else error('invalid type in compose expression') end end local call = `self:init(minlen) for i,v in ipairs(pstrs) do call = `[call]:push([v.str],[v.len]) end return call end) m.acc.metamethods.__lshift = terralib.overloadedfunction('(<<)', { terra(self: &m.acc, str: rawstring) return self: push(str,0) end; terra(self: &m.acc, str: lib.mem.ptr(int8)) return self:ppush(str ) end; }) m.box = terralib.memoize(function(ty) local b = struct { obj: ty storage: int8[0] } b.name = string.format('bytebox<%s>', ty.name) b.methods.mk = terra(sz: intptr) return [&b](lib.mem.heapa_raw(sizeof(b) + sz)) end terra b:free() lib.mem.heapf(self) end -- enhhhhh return b end) m.encapsulate = function(ty, vals) local memreq_const = sizeof(ty) local ptr = symbol(&int8) local box = symbol(&m.box(ty)) local memreq_exp = `0 local copiers = {} for k,v in pairs(vals) do local ty = (`box.obj.[k]).tree.type local kp if ty.ptr_basetype then kp = quote [box].obj.[k] = [ty] { [ptr] = [&ty.ptr_basetype]([ptr]) } ; end else kp = quote [box].obj.[k] = [ty]([ptr]) ; end end local cpy if type(v) ~= 'table' or #v ~= 2 then cpy = quote [kp] ; [ptr] = m.cpy(ptr, v) end end if type(v) == 'string' then memreq_const = memreq_const + #v + 1 elseif type(v) == 'table' and v.tree and (v.tree.type.ptr_basetype == int8 or v.tree.type.ptr_basetype == uint8) then cpy = quote [kp]; [ptr] = [&int8](lib.mem.cpy([ptr], [v].ptr, [v].ct)) end if ty.ptr_basetype then cpy = quote [cpy]; [box].obj.[k].ct = [v].ct end end elseif type(v) == 'table' and v.asvalue and type(v:asvalue()) == 'string' then local str = tostring(v:asvalue()) memreq_const = memreq_const + #str + 1 elseif type(v) == 'table' and #v == 2 then local str,sz = v[1],v[2] if type(sz) == 'number' then memreq_const = memreq_const + sz elseif type(sz:asvalue()) == 'number' then memreq_const = memreq_const + sz:asvalue() else memreq_exp = `[sz] + [memreq_exp] end cpy = quote [kp] ; [ptr] = [&int8](lib.mem.cpy([ptr], str, sz)) end if ty.ptr_basetype then cpy = quote [cpy]; [box].obj.[k].ct = sz end end else memreq_exp = `(m.sz(v) + 1) + [memreq_exp] -- make room for NUL if ty.ptr_basetype then cpy = quote [cpy]; [box].obj.[k].ct = m.sz(v) end end end copiers[#copiers + 1] = cpy end return quote var sz: intptr = memreq_const + [memreq_exp] var [box] = [&m.box(ty)](lib.mem.heapa_raw(sz)) var [ptr] = [box].storage [copiers] in [lib.mem.ptr(ty)] { ct = 1, ptr = &([box].obj) } end end return m |
Deleted string.t version [a0d1de486b].
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 |
-- vim: ft=terra -- string.t: string classes local m = {} struct m.acc { buf: rawstring sz: intptr run: intptr space: intptr } local terra biggest(a: intptr, b: intptr) if a > b then return a else return b end end m.acc.methods = { init = terra(self: &m.acc, run: intptr) lib.dbg('initializing string accumulator') self.buf = [rawstring](lib.mem.heapa_raw(run)) self.run = run self.space = run self.sz = 0 end; free = terra(self: &m.acc) lib.dbg('freeing string accumulator') if self.buf ~= nil and self.space > 0 then lib.mem.heapf(self.buf) end end; crush = terra(self: &m.acc) lib.dbg('crushing string accumulator') self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.sz)) self.space = self.sz return self end; } m.acc.methods.finalize = terra(self: &m.acc) lib.dbg('finalizing string accumulator') self:crush() var pt: lib.mem.ptr(int8) pt.ptr = self.buf pt.ct = self.sz self.buf = nil self.sz = 0 return pt end; m.acc.methods.push = terra(self: &m.acc, str: rawstring, len: intptr) lib.dbg('pushing "',str,'" onto accumulator') if self.buf == nil then self:init(self.run) end if len == 0 then len = lib.str.sz(str) end if len >= self.space - self.sz then self.space = self.space + biggest(self.run,len + 1) self.buf = [rawstring](lib.mem.heapr_raw(self.buf, self.space)) end lib.mem.cpy(self.buf + self.sz, str, len) self.sz = self.sz + len self.buf[self.sz] = 0 return self end; m.acc.methods.ppush = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) return self end; m.acc.methods.merge = terra(self: &m.acc, str: lib.mem.ptr(int8)) self:push(str.ptr, str.ct) str:free() return self end; return m |
< < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |