Overview
| Comment: | iterate on user mgmt UI |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
f09cd181619364e959c3e0fd19b18d8c |
| User & Date: | lexi on 2021-01-02 18:32:02 |
| Other Links: | manifest | tags |
Context
|
2021-01-04
| ||
| 06:44 | add likes, retweets, and iterate on a whole bunch of other shit check-in: 78b0198f09 user: lexi tags: trunk | |
|
2021-01-02
| ||
| 18:32 | iterate on user mgmt UI check-in: f09cd18161 user: lexi tags: trunk | |
| 04:47 | work on admin ui check-in: 7129658e1d user: lexi tags: trunk | |
Changes
Modified render/conf/users.t from [4494d99300] to [09fa445b20].
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
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
case [uint16](3) then acc:lpush('⚜️') end
case [uint16](4) then acc:lpush('🗡') end
case [uint16](5) then acc:lpush('🗝') end
else acc:lpush('🕴')
end
end
local num_field = macro(function(acc,name,lbl,min,max,value)
name = name:asvalue()
lbl = lbl:asvalue()
return quote
var decbuf: int8[21]
in acc:lpush([string.format('<div class="elem small"><label for="%s">%s</label><input type="number" id="%s" name="%s" min="', name, lbl, name, name)])
:push(lib.math.decstr(min, &decbuf[20]),0)
:lpush('" max="'):push(lib.math.decstr(max, &decbuf[20]),0)
:lpush('" value="'):push(lib.math.decstr(value, &decbuf[20]),0):lpush('"></div>')
end
end)
local terra
push_checkbox(acc: &lib.str.acc, name: pstr, lbl: pstr, on: bool, enabled: bool)
acc:lpush('<label><input type="checkbox" name="'):ppush(name):lpush('"')
if on then acc:lpush(' checked') end
if not enabled then acc:lpush(' disabled') end
acc:lpush('> '):ppush(lbl):lpush('</label>')
end
local mode_local, mode_remote, mode_staff, mode_peers, mode_peons, mode_all = 0,1,2,3,4,5
local terra
render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr
if path.ct == 3 then
var uid, ok = lib.math.shorthand.parse(path(2).ptr,path(2).ct)
if not ok then goto e404 end
var user = co.srv:actor_fetch_uid(uid)
-- FIXME allow xids as well, for manual queries
if not user then goto e404 end
defer user:free()
if not co.who:overpowers(user.ptr) then goto e403 end
var islinkct = false
var cinp: lib.str.acc cinp:init(128)
var clnk: lib.str.acc clnk:compose('<hr>')
cinp:lpush('<div class="elem-group">')
if co.who.rights.powers.herald() then
var sanitized: pstr
if user.ptr.epithet == nil
then sanitized = pstr {ptr='', ct=0}
else sanitized = lib.html.sanitize(cs(user.ptr.epithet),true)
end
cinp:lpush('<div class="elem"><label for="epithet">epithet</label><input type="text" id="epithet" name="epithet" value="'):ppush(sanitized):lpush('"></div>')
if user.ptr.epithet ~= nil then sanitized:free() end
end
if user.ptr.rights.rank > 0 and (co.who.rights.powers.elevate() or co.who.rights.powers.demote()) then
var max = co.who.rights.rank
if not co.who.rights.powers.elevate() then max = user.ptr.rights.rank end
var min = co.srv.cfg.nranks
if not co.who.rights.powers.demote() then min = user.ptr.rights.rank end
num_field(cinp, 'rank', 'rank', max, min, user.ptr.rights.rank)
end
if co.who.rights.powers.invite() or co.who.rights.powers.discipline() then
var min = 0
if not (co.who.rights.powers.discipline() or
co.who.rights.powers.demote() and co.who.rights.powers.invite())
then min = user.ptr.rights.invites end
var max = co.srv.cfg.maxinvites
if not co.who.rights.powers.invite() then max = user.ptr.rights.invites end
num_field(cinp, 'invites', 'invites', min, max, user.ptr.rights.invites)
end
cinp:lpush('</div><div class="check-panel">')
if (user.ptr.rights.rank == 0 and co.who.rights.powers.elevate()) or
(user.ptr.rights.rank > 0 and co.who.rights.powers.demote()) then
push_checkbox(&cinp, 'staff', 'site staff member', user.ptr.rights.rank > 0, true)
end
cinp:lpush('</div>')
if co.who.rights.powers.elevate() or
co.who.rights.powers.demote() then
var map = array([lib.store.privmap])
cinp:lpush('<label>powers</label><div class="check-panel">')
for i=0, [map.type.N] do
if (co.who.rights.powers and map[i].priv) == map[i].priv then
var name: int8[64]
var on = (user.ptr.rights.powers and map[i].priv) == map[i].priv
var enabled = (on and co.who.rights.powers.demote()) or
((not on) and co.who.rights.powers.elevate())
lib.str.cpy(&name[0], 'allow-')
lib.str.ncpy(&name[6], map[i].name.ptr, map[i].name.ct)
push_checkbox(&cinp, pstr{ptr=&name[0],ct=map[i].name.ct+6},
map[i].name, on, enabled)
end
end
cinp:lpush('</div>')
end
-- TODO black mark system? e.g. resolution option for badthink reports
-- adds a black mark to the offending user; they can be automatically banned
-- or brought up for review after a certain number of offenses; possibly lower
-- set of default privs for marked users
var cinpp = cinp:finalize() defer cinpp:free()
var clnkp: pstr
if islinkct then clnkp = clnk:finalize() else
clnk:free()
clnkp = pstr { ptr='', ct=0 }
end
var unym: lib.str.acc unym:init(64)
unym:lpush('<a href="/')
if user(0).origin ~= 0 then unym:lpush('@') end
do var sanxid = lib.html.sanitize(user(0).xid, true)
................................................................................
var pg = data.view.conf_user_ctl {
name = unym:finalize();
inputcontent = cinpp;
linkcontent = clnkp;
}
var ret = pg:tostr()
pg.name:free()
if islinkct then clnkp:free() end
return ret
else
var modes = array(P'local', P'remote', P'staff', P'titled', P'peons', P'all')
var idbuf: int8[lib.math.shorthand.maxlen]
var ulst: lib.str.acc ulst:init(256)
var mode: uint8 = mode_local
var modestr = co:pgetv('show')
|
|
>
>
>
<
>
>
>
>
|
|
|
|
|
>
<
<
<
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
<
|
|
>
>
>
>
>
>
>
>
<
<
<
<
<
<
<
<
|
|
>
|
|
|
|
|
|
<
>
|
<
|
|
|
|
<
|
>
|
|
|
|
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
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
case [uint16](3) then acc:lpush('⚜️') end
case [uint16](4) then acc:lpush('🗡') end
case [uint16](5) then acc:lpush('🗝') end
else acc:lpush('🕴')
end
end
local push_num_field = macro(function(acc,name,lbl,min,max,value,disable)
name = name:asvalue()
lbl = lbl:asvalue()
local start = '<div class="elem small">'
local enabled = start .. string.format('<label for="%s">%s</label><input type="number" id="%s" name="%s" min="', name, lbl, name, name)
local disabled = start .. string.format('<label>%s</label><div class="txtbox">', lbl)
return quote
var decbuf: int8[21]
if disable then
acc:lpush([disabled])
:push(lib.math.decstr(value, &decbuf[20]),0):lpush('</div></div>')
else
acc:lpush([enabled]):push(lib.math.decstr(min, &decbuf[20]),0)
:lpush('" max="'):push(lib.math.decstr(max, &decbuf[20]),0)
:lpush('" value="'):push(lib.math.decstr(value, &decbuf[20]),0):lpush('"></div>')
end
end
end)
local input_pusher = function(kind,wrap,uniq)
local fn = terra(acc: &lib.str.acc, name: pstr, val: pstr, lbl: pstr, on: bool, enabled: bool, class: pstr)
if wrap then acc:lpush('<label>') end
acc:lpush(['<input type="'..kind..'" name="']):ppush(name)
if not wrap then
acc:lpush('" id="'):ppush(name)
if uniq then acc:lpush('-'):ppush(val) end
end
if val:ref() then acc:lpush('" value="'):ppush(val) end
if class:ref() then acc:lpush('" class="'):ppush(class) end
acc:lpush('"')
if on then acc:lpush(' checked') end
if not enabled then acc:lpush(' disabled') end
acc:lpush('>')
if not wrap then acc:lpush('<label for="'):ppush(name)
if uniq then acc:lpush('-'):ppush(val) end
acc:lpush('">')
else acc:lpush(' ') end
acc:ppush(lbl):lpush('</label>')
end
fn.name = string.format('push-input-element<%q>',kind)
return fn
end
local push_checkbox = input_pusher('checkbox',true,false)
local push_pickbox = input_pusher('checkbox',false,false)
local push_radio = input_pusher('radio',false,true)
local mode_local, mode_remote, mode_staff, mode_peers, mode_peons, mode_all = 0,1,2,3,4,5
local terra
render_conf_users(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr
if path.ct == 3 then
var uid, ok = lib.math.shorthand.parse(path(2).ptr,path(2).ct)
if not ok then goto e404 end
var user = co.srv:actor_fetch_uid(uid)
-- FIXME allow xids as well, for manual queries
if not user then goto e404 end
defer user:free()
if not co.who:overpowers(user.ptr) then goto e403 end
var cinp: lib.str.acc cinp:init(256)
var clnk: lib.str.acc clnk:init(512)
cinp:lpush('<div class="elem-group">')
if user.ptr.rights.rank > 0 and (co.who.rights.powers.elevate() or co.who.rights.powers.demote()) then
var max = co.who.rights.rank
if not co.who.rights.powers.elevate() then max = user.ptr.rights.rank end
var min = co.srv.cfg.nranks
if not co.who.rights.powers.demote() then min = user.ptr.rights.rank end
push_num_field(cinp, 'rank', 'rank', max, min, user.ptr.rights.rank, user.ptr.id == co.who.id)
end
if co.who.rights.powers.herald() then
var sanitized: pstr
if user.ptr.epithet == nil
then sanitized = pstr {ptr='', ct=0}
else sanitized = lib.html.sanitize(cs(user.ptr.epithet),true)
end
cinp:lpush('<div class="elem"><label for="epithet">epithet</label><input type="text" id="epithet" name="epithet" value="'):ppush(sanitized):lpush('"></div>')
if user.ptr.epithet ~= nil then sanitized:free() end
end
if co.who.rights.powers.invite() or co.who.rights.powers.discipline() then
var min = 0
if not (co.who.rights.powers.discipline() or
co.who.rights.powers.demote() and co.who.rights.powers.invite())
then min = user.ptr.rights.invites end
var max = co.srv.cfg.maxinvites
if not co.who.rights.powers.invite() then max = user.ptr.rights.invites end
push_num_field(cinp, 'invites', 'invites', min, max, user.ptr.rights.invites, false)
end
cinp:lpush('</div><div class="elem"><div class="check-panel">')
if user.ptr.id ~= co.who.id and
((user.ptr.rights.rank == 0 and co.who.rights.powers.elevate()) or
(user.ptr.rights.rank > 0 and co.who.rights.powers.demote())) then
push_checkbox(&cinp, 'staff', pstr.null(), 'site staff member', user.ptr.rights.rank > 0, true, pstr.null())
end
cinp:lpush('</div></div>')
if (co.who.rights.powers.elevate() or
co.who.rights.powers.demote()) and user.ptr.id ~= co.who.id then
var map = array([lib.store.privmap])
cinp:lpush('<details><summary>powers</summary><div class="pick-list">')
for i=0, [map.type.N] do
if (co.who.rights.powers and map[i].priv):sz() > 0 then
var on = (user.ptr.rights.powers and map[i].priv):sz() > 0
var enabled = ( on and co.who.rights.powers.demote() ) or
((not on) and co.who.rights.powers.elevate())
var namea: lib.str.acc namea:compose('power-', map[i].name)
var name = namea:finalize()
push_pickbox(&cinp, name, pstr.null(), map[i].name, on, enabled, pstr.null())
name:free()
end
end
cinp:lpush('</div></details>')
end
-- TODO black mark system? e.g. resolution option for badthink reports
-- adds a black mark to the offending user; they can be automatically banned
-- or brought up for review after a certain number of offenses; possibly lower
-- set of default privs for marked users
var cinpp = cinp:finalize() defer cinpp:free()
var clnkp: pstr
if clnk.sz > 0 then clnkp = clnk:finalize() else
clnk:free()
clnkp = pstr { ptr='', ct=0 }
end
var unym: lib.str.acc unym:init(64)
unym:lpush('<a href="/')
if user(0).origin ~= 0 then unym:lpush('@') end
do var sanxid = lib.html.sanitize(user(0).xid, true)
................................................................................
var pg = data.view.conf_user_ctl {
name = unym:finalize();
inputcontent = cinpp;
linkcontent = clnkp;
}
var ret = pg:tostr()
pg.name:free()
if clnkp.ct > 0 then clnkp:free() end
return ret
else
var modes = array(P'local', P'remote', P'staff', P'titled', P'peons', P'all')
var idbuf: int8[lib.math.shorthand.maxlen]
var ulst: lib.str.acc ulst:init(256)
var mode: uint8 = mode_local
var modestr = co:pgetv('show')
|
Modified srv.t from [6be667433b] to [34fad9fa1a].
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
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
|
| |
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
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(256)
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
|
Modified static/style.scss from [f40a20016f] to [4fd9d6949f].
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
...
767
768
769
770
771
772
773
774
775
|
}
form {
margin: 0.15in 0;
> p:first-child { margin-top: 0; }
> p:last-child { margin-bottom: 0; }
.elem {
margin: 0.1in 0;
label { display:block; font-weight: bold; padding: 0.03in 0; }
.txtbox {
@extend %serif;
box-sizing: border-box;
padding: 0.08in 0.1in;
border: 1px solid black;
background: tone(-55%);
}
input, textarea, .txtbox {
display: block;
width: 100%;
}
textarea { resize: vertical; min-height: 2in; }
}
:is(.elem,.elem-group) + %button { margin-left: 50%; width: 50%; }
.elem-group {
display: flex;
flex-flow: row;
> .elem {
flex-shrink: 1;
flex-grow: 1;
margin-left: 0.1in;
................................................................................
text-align: center;
padding: 0.3em 0;
margin: 0.2em 0.1em;
cursor: default;
}
}
:is(%button, a[href]).neg { --co: 60 }
:is(%button, a[href]).pos { --co: -30 }
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
...
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
|
}
form {
margin: 0.15in 0;
> p:first-child { margin-top: 0; }
> p:last-child { margin-bottom: 0; }
.elem {
margin: 0.1in 0;
> label,summary { display:block; font-weight: bold; padding: 0.03in 0; }
> .txtbox {
@extend %serif;
box-sizing: border-box;
padding: 0.08in 0.1in;
border: 1px solid black;
background: tone(-55%);
}
> input, textarea, .txtbox {
display: block;
width: 100%;
}
> textarea { resize: vertical; min-height: 2in; }
}
body.conf & > %button { margin-left: 50%; width: 50%; }
.elem-group {
display: flex;
flex-flow: row;
> .elem {
flex-shrink: 1;
flex-grow: 1;
margin-left: 0.1in;
................................................................................
text-align: center;
padding: 0.3em 0;
margin: 0.2em 0.1em;
cursor: default;
}
}
:is(%button, a[href]).neg { --co: 30 }
:is(%button, a[href]).pos { --co: -30 }
.pick-list {
display: flex;
flex-flow: row wrap;
padding: 0.1in;
background-color: tone(-50%);
border: 1px solid tone(-53%);
border-top: 1px solid tone(-57%);
border-bottom: 1px solid tone(-45%);
margin: 0.3em 0;
details & { border: none; background: none; }
> input[type="radio"], > input[type="checkbox"] {
display: none;
&+label {
display: block;
flex-grow: 1;
padding: 0.08in 0.05in;
margin: 0.03in;
flex-basis: 15%;
cursor: pointer;
transition: 0.3s;
text-align: center;
border: 1px solid transparent;
text-shadow: 1px 1px black;
color: otone(15%);
border-radius: 4px;
&:nth-child(7n+1) { --co: -10 } //silly hack
&:nth-child(7n+2) { --co: -35 }
&:nth-child(7n+3) { --co: -20 }
&:nth-child(7n+4) { --co: -50 }
&:nth-child(7n+5) { --co: -40 }
&:nth-child(7n+6) { --co: -5 }
&:nth-child(7n+7) { --co: -25 }
}
&+label:hover {
background-color: otone(-35%);
color: white;
}
&:checked+label {
border-top: 1px solid otone(-10%);
border-bottom: 1px solid otone(-50%);
background: linear-gradient(to bottom, otone(-25%,-0.2), otone(-28%,-0.4) 35%, otone(-30%,-0.7));
color: white;
box-shadow: 0 0 0 1px tone(-60%);
&:hover {
border-top: 1px solid otone(10%);
border-bottom: 1px solid otone(-60%);
font-weight: bold;
}
}
}
}
details {
//border: 1px solid tone(-60%);
border-top: 1px solid tone(-40%);
border-bottom: 1px solid tone(-60%);
border-radius: 3px;
padding: 0.05in 0.3in;
margin: 0.08in 0;
// background: linear-gradient(to top, tone(-55%), tone(-50%));
background: tone(-50%);
& > summary {
display: block;
margin: 0 -0.25in;
cursor: pointer;
user-select: none;
text-decoration: underline;
text-decoration-color: tone(10%,-0.5);
text-underline-offset: 0.1em;
text-shadow: 1px 1px black;
font-weight: normal;
&:hover {
color: white;
text-decoration-color: tone(10%,-0.1);
}
&::marker { display: none; }
&::-webkit-details-marker { display: none; }
&::before {
display: inline-block;
content: '➤';
padding: 0 0.3em;
color: tone(-30%);
transition: 0.4s;
}
}
&[open] {
// background: linear-gradient(to bottom, tone(-55%), tone(-50%));
border-bottom: 1px solid tone(-40%);
border-top: 1px solid tone(-60%);
> summary {
font-weight: bold;
&::before {
transform: rotate(90deg) scale(1.1);
color: tone(-20%);
text-shadow: 0 0 8px tone(-30%);
}
}
}
}
|
Modified str.t from [265a0fa659] to [1e93ad8eb5].
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
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
................................................................................
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
|
>
>
>
>
|
>
>
>
>
|
|
>
|
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
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
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')
if run == 0 then
lib.warn('attempted to allocate zero-length string accumulator')
self.buf = nil
else
self.buf = [rawstring](lib.mem.heapa_raw(run))
if self.buf == nil then
lib.warn('string buffer allocation failed, very little memory availble')
end
end
self.run = lib.trn(self.buf == nil, 0, run)
self.space = self.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
................................................................................
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 self.buf == nil then lib.warn('attempted to push string onto unallocated accumulator') return self 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
|
Modified view/conf-user-ctl.tpl from [9830040aea] to [7abbc95a91].
1 2 3 4 5 6 7 8 9 |
<form method="post">
<div class="elem">
<label>user</label>
<div class="txtbox">@name</div>
</div>
@inputcontent
<button>alter</button>
@linkcontent
</form>
|
< > |
1 2 3 4 5 6 7 8 9 |
<form method="post">
<div class="elem">
<label>user</label>
<div class="txtbox">@name</div>
</div>
@inputcontent
<button>alter</button>
</form>
@linkcontent
|