Make assoldap compatible with multi-value fields.
[shellsnippets/shellsnippets.git] / mksh / rechte-mock.shar
1 # This is a bigger CGI sample application.
2 #-
3 # This is a shell archive.  Save it in a file, remove anything before
4 # this line, and then unpack it by entering "sh file".  Note, it may
5 # create directories; files and directories will be owned by you and
6 # have default permissions.
7 #
8 # This archive contains:
9 #
10 #       rechte-mock/.htaccess
11 #       rechte-mock/addrole.cgi
12 #       rechte-mock/common
13 #       rechte-mock/grpimport.cgi
14 #       rechte-mock/grprole.cgi
15 #       rechte-mock/roleperm.cgi
16 #       rechte-mock/se.cgi
17 #
18 echo x - rechte-mock/.htaccess
19 sed 's/^X//' >rechte-mock/.htaccess << 'END-of-rechte-mock/.htaccess'
20 X# $Id$
21 X
22 XOptions +ExecCGI
23 XAddHandler cgi-script .cgi
24 END-of-rechte-mock/.htaccess
25 echo x - rechte-mock/addrole.cgi
26 sed 's/^X//' >rechte-mock/addrole.cgi << 'END-of-rechte-mock/addrole.cgi'
27 X#!/bin/mksh
28 X# $Id$
29 X#-
30 X# Copyright © 2011, 2012
31 X#      Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
32 X# Licenced under the AGPLv3
33 X
34 X. "$(dirname "$0")"/common
35 X
36 Xparse_getparms Submit name
37 Xif [[ -n $parm_Submit && -n $parm_name ]]; then
38 X       print 0 >data/roles/"$parm_name"
39 X       html_open "Add Role"
40 X       print "<p>Role $parm_name added successfully.</p>"
41 X       html_close
42 X       exit 0
43 Xfi
44 X
45 Xhtml_open "Add Role"
46 Xprint '<form method="get" action="addrole.cgi">'
47 Xprint '<p>New role: <input type="text" name="name" size="20" /></p>'
48 Xprint '<p><input type="submit" name="Submit" value="Rolle hinzufügen" /></p>'
49 Xprint '</form>'
50 Xprint '<p>Existierende Rollen:</p><ul>'
51 Xcd data/roles
52 Xfor i in *; do
53 X       print -r " <li>$i</li>"
54 Xdone
55 Xprint '</ul>'
56 Xhtml_close
57 Xexit 0
58 END-of-rechte-mock/addrole.cgi
59 echo x - rechte-mock/common
60 sed 's/^X//' >rechte-mock/common << 'END-of-rechte-mock/common'
61 X# $Id$
62 X#-
63 X# Copyright © 2011, 2012
64 X#      Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
65 X# Licenced under the AGPLv3
66 X
67 Xexport LC_ALL=C
68 Xunset LANGUAGE
69 X
70 X# check for new enough mksh version
71 X#set -A PIPESTATUS -- 23 42
72 Xfalse | true | true
73 Xset -A rv -- "${PIPESTATUS[@]}"
74 Xif [[ ${#rv[*]} != 3 || ${rv[0]} != 1 || ${rv[1]} != 0 || ${rv[2]} != 0 ]]; then
75 X       print -u2 need mksh R40
76 X       exit 255
77 Xfi
78 X
79 X# ensure cwd is right and data dirs exist
80 Xcd "$(dirname "$0")"
81 Xmkdir -p data/{roles,groups/{isactive,roles}}
82 X
83 X# Base64 encoder/decoder
84 Xset -A Lb64encode_code -- A B C D E F G H I J K L M N O P Q R S T U V W X Y Z \
85 X    a b c d e f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 + /
86 Xfunction b64encode {
87 X       [[ -o utf8-mode ]]; local u=$?
88 X       set +U
89 X       local c s t
90 X       if (( $# )); then
91 X               read -raN-1 s <<<"$*"
92 X               unset s[${#s[*]}-1]
93 X       else
94 X               read -raN-1 s
95 X       fi
96 X       local -i i=0 n=${#s[*]} j v
97 X
98 X       while (( i < n )); do
99 X               (( v = s[i++] << 16 ))
100 X               (( j = i < n ? s[i++] : 0 ))
101 X               (( v |= j << 8 ))
102 X               (( j = i < n ? s[i++] : 0 ))
103 X               (( v |= j ))
104 X               t+=${Lb64encode_code[v >> 18]}${Lb64encode_code[v >> 12 & 63]}
105 X               c=${Lb64encode_code[v >> 6 & 63]}
106 X               if (( i <= n )); then
107 X                       t+=$c${Lb64encode_code[v & 63]}
108 X               elif (( i == n + 1 )); then
109 X                       t+=$c=
110 X               else
111 X                       t+===
112 X               fi
113 X               if (( ${#t} == 76 || i >= n )); then
114 X                       print $t
115 X                       t=
116 X               fi
117 X       done
118 X       (( u )) || set -U
119 X}
120 X
121 Xfunction b64decode {
122 X       typeset c s="$*" t=
123 X       typeset -i i=0 n=${#s} p=0 v x
124 X       typeset -i1 o
125 X
126 X       while (( i < n )); do
127 X               c=${s:(i++):1}
128 X               case $c {
129 X               (=)     break ;;
130 X               ([A-Z]) (( v = 1#$c - 65 )) ;;
131 X               ([a-z]) (( v = 1#$c - 71 )) ;;
132 X               ([0-9]) (( v = 1#$c + 4 )) ;;
133 X               (+)     v=62 ;;
134 X               (/)     v=63 ;;
135 X               (*)     continue ;;
136 X               }
137 X               (( x = (x << 6) | v ))
138 X               case $((p++)) {
139 X               (0)     continue ;;
140 X               (1)     (( o = (x >> 4) & 255 )) ;;
141 X               (2)     (( o = (x >> 2) & 255 )) ;;
142 X               (3)     (( o = x & 255 ))
143 X                       p=0
144 X                       ;;
145 X               }
146 X               t=$t${o#1#}
147 X       done
148 X       print -nr -- "$t"
149 X}
150 X
151 X# make an LDAP request
152 XLDAP_SERVER=dc-slave.lan.tarent.de
153 Xfunction ldapshow {
154 X       local rv
155 X
156 X       ldapsearch -xLLL -ZZ -h "$LDAP_SERVER" "$@" | \
157 X           tr '\n' $'\a' | sed -e $'s/\a //g' | tr $'\a' '\n'
158 X       set -A rv -- "${PIPESTATUS[@]}"
159 X       return ${rv[0]}
160 X}
161 X
162 X# start and finish an HTML page
163 Xfunction html_open {
164 X       local title="$*"
165 X
166 X       cat <<EOF
167 XContent-Type: text/html; charset=utf-8
168 X
169 X<?xml version="1.0"?>\r
170 X<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
171 X "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
172 X<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><head>
173 X <meta http-equiv="content-type" content="text/html; charset=utf-8" />
174 X <title>${title}</title>
175 X</head><body>
176 XEOF
177 X}
178 Xfunction html_close {
179 X       print '</body></html>'
180 X}
181 X
182 X# set of permission bits and their names
183 Xset -A perm_bits -- \
184 X    'Eigene Leistungen eintragen/ändern/löschen/umbuchen' \
185 X    'Fremde Leistungen in einem Projekt sehen' \
186 X    'Fremde Leistungen eines Bereichs sehen' \
187 X    'Alle fremden Leistungen sehen' \
188 X    'Fremde Leistungen löschen' \
189 X    'Fremde Leistungen umbuchen' \
190 X    'Fremde Leistungen importieren/exportieren' \
191 X    'Eigene Überstunden eintragen/ändern/löschen' \
192 X    'Fremde Überstunden in einem Projekt sehen' \
193 X    'Fremde Überstunden in einem Projekt exportieren' \
194 X    'Fremde Überstunden eines Bereichs sehen' \
195 X    'Fremde Überstunden eines Bereichs exportieren' \
196 X    'Alle fremden Überstunden sehen' \
197 X    'Alle Überstunden eines Bereichs exportieren' \
198 X    'Fremde Überstunden eintragen/löschen/abfeiern' \
199 X    'Eigene Abwesenheiten beantragen/ändern/löschen' \
200 X    'Abwesenheiten genehmigen' \
201 X    'Fremde Abwesenheiten in einem Projekt sehen' \
202 X    'Fremde Abwesenheiten eines Bereichs sehen' \
203 X    'Alle fremden Abwesenheiten sehen' \
204 X    'Alle fremden Abwesenheiten exportieren' \
205 X    'Fremde Abwesenheiten löschen/ändern' \
206 X    'Kunden anlegen/ändern/löschen' \
207 X    'Projekte anlegen' \
208 X    'Eigene Projekte ändern/löschen' \
209 X    'Projekte eines Bereichs ändern/löschen' \
210 X    'Alle Projekte ändern/löschen' \
211 X    'Eigene Projekte sehen' \
212 X    'Projekte eines Bereichs sehen' \
213 X    'Alle Projekte sehen' \
214 X    'Aufträge anlegen' \
215 X    'Eigene Aufträge ändern/löschen' \
216 X    'Aufträge eines Bereichs ändern/löschen' \
217 X    'Alle Aufträge ändern/löschen' \
218 X    'Eigene Aufträge sehen' \
219 X    'Aufträge eines Bereichs sehen' \
220 X    'Alle Aufträge sehen' \
221 X    'Rechnungen zu Aufträgen sehen' \
222 X    'Positionen anlegen' \
223 X    'Eigene Positionen ändern/löschen' \
224 X    'Positionen eines Bereichs ändern/löschen' \
225 X    'Alle Positionen ändern löschen' \
226 X    'Eigene Positionen sehen' \
227 X    'Positionen eines Bereichs sehen' \
228 X    'Alle Positionen sehen' \
229 X    'Ressourcen zu Positionen hinzufügen/löschen' \
230 X    'Ressourcen anlegen/bearbeiten/sperren/löschen' \
231 X    'Ressourcen einsehen' \
232 X    'Ressourcen Rechte zuteilen' \
233 X    'Auftragsrechnungen einstellen/bearbeiten/löschen' \
234 X    'Auftragsrechnungen sehen' \
235 X    'Projektrechnungen einstellen/bearbeiten/löschen' \
236 X    'Projektrechnungen sehen' \
237 X    'activity Einstellungen ändern' \
238 X# add only here; the keys are indicēs
239 X
240 X# parse query string
241 Xfunction parse_getparms {
242 X       local saveIFS flds fld cfld k v
243 X
244 X       saveIFS=$IFS
245 X       IFS='&;'
246 X       set -A flds -- $QUERY_STRING
247 X       IFS=$saveIFS
248 X
249 X       for cfld in "$@"; do
250 X               eval parm_$cfld=
251 X       done
252 X
253 X       for fld in "${flds[@]}"; do
254 X               k=${fld%%=*}
255 X               v=${fld#*=}
256 X               for cfld in "$@"; do
257 X                       [[ $k = "$cfld" ]] || continue
258 X                       eval parm_$cfld=\$v
259 X                       break
260 X               done
261 X       done
262 X}
263 END-of-rechte-mock/common
264 echo x - rechte-mock/grpimport.cgi
265 sed 's/^X//' >rechte-mock/grpimport.cgi << 'END-of-rechte-mock/grpimport.cgi'
266 X#!/bin/mksh
267 X# $Id$
268 X#-
269 X# Copyright © 2011, 2012
270 X#      Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
271 X# Licenced under the AGPLv3
272 X
273 X. "$(dirname "$0")"/common
274 X
275 Xcurcn=
276 Xldapshow -b cn=groups,dc=tarent,dc=de objectClass=posixGroup cn | \
277 X    while read key value; do
278 X       case $key {
279 X       (cn:)   curcn=$value ;;
280 X       (cn::)  curcn=$(b64decode "$value") ;;
281 X       }
282 X
283 X       # ignore unknown lines / keys
284 X       [[ -z $key ]] || continue
285 X       # empty lines separate records
286 X
287 X       if [[ -n $curcn ]]; then
288 X               [[ $curcn = */* ]] || print -r -- "$curcn"
289 X       fi
290 X       curcn=
291 Xdone | sort -fu |&
292 XIFS=$'\n' read -p -A -N-1 all_ldap_groups
293 Xall_ldap_groups_=${#all_ldap_groups[*]}
294 X
295 Xset -A all_ldap_groups_enabledp
296 X
297 X#QUERY_STRING='grp%5B%5D=Administrators&grp%5B%5D=Controller&Submit=Gruppen+freischalten'
298 Xparse_getparms Submit
299 Xif [[ -n $parm_Submit ]]; then
300 X       saveIFS=$IFS
301 X       IFS='&;'
302 X       set -A flds -- $QUERY_STRING
303 X       IFS=$saveIFS
304 X
305 X       for fld in "${flds[@]}"; do
306 X               k=${fld%%=*}
307 X               [[ $k = 'grp%5B%5D' || $k = 'grp%5b%5d' || $k = 'grp[]' ]] || continue
308 X               v=${fld#*=}
309 X               v=${v//+/ }
310 X               i=-1
311 X               while (( ++i < all_ldap_groups_ )); do
312 X                       [[ ${all_ldap_groups[i]} = "$v" ]] || continue
313 X                       all_ldap_groups_enabledp[i]=1
314 X                       break
315 X               done
316 X       done
317 X
318 X       i=-1
319 X       while (( ++i < all_ldap_groups_ )); do
320 X               n=${all_ldap_groups[i]}
321 X               x=0
322 X               [[ ${all_ldap_groups_enabledp[i]} = 1 ]] && x=1
323 X               print $x >data/groups/isactive/"$n"
324 X       done
325 Xfi
326 X
327 Xset -A all_ldap_groups_enabledp
328 X
329 Xi=-1
330 Xwhile (( ++i < all_ldap_groups_ )); do
331 X       n=${all_ldap_groups[i]}
332 X       x=0
333 X       [[ -s data/groups/isactive/$n && \
334 X           "$(<data/groups/isactive/$n)" = *1* ]] && x=1
335 X       all_ldap_groups_enabledp[i]=$x
336 Xdone
337 X
338 Xhtml_open "Import LDAP groups"
339 Xprint '<form method="get" action="grpimport.cgi">'
340 Xprint '<div><table border="1">'
341 Xprint '<tr><th width="10em">Import?</th><th>Group Common Name</th></tr>'
342 Xi=-1
343 Xwhile (( ++i < all_ldap_groups_ )); do
344 X       n=${all_ldap_groups[i]}
345 X       x=${all_ldap_groups_enabledp[i]}
346 X       print -n '<td><input type="checkbox" name="grp[]" value="'"$n"\"
347 X       (( x )) && print -n ' checked="checked"'
348 X       print " /></td><td>$n</td></tr>"
349 Xdone
350 Xprint '</table></div><div>'
351 Xprint '<p><input type="submit" name="Submit" value="Gruppen freischalten" /></p>'
352 Xprint '</div></form>'
353 Xhtml_close
354 Xexit 0
355 END-of-rechte-mock/grpimport.cgi
356 echo x - rechte-mock/grprole.cgi
357 sed 's/^X//' >rechte-mock/grprole.cgi << 'END-of-rechte-mock/grprole.cgi'
358 X#!/bin/mksh
359 X# $Id$
360 X#-
361 X# Copyright © 2011, 2012
362 X#      Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
363 X# Licenced under the AGPLv3
364 X
365 X. "$(dirname "$0")"/common
366 X
367 X(cd data/groups/isactive; for n in *; do
368 X       [[ $(<$n) = *1* ]] && print -r -- "$n"
369 Xdone) |&
370 XIFS=$'\n' read -p -A -N-1 ldap_groups
371 X
372 X(cd data/roles; for n in *; do
373 X       [[ -s $n ]] && print -r -- "$n"
374 Xdone) |&
375 XIFS=$'\n' read -p -A -N-1 roles
376 X
377 Xparse_getparms Submit
378 Xif [[ -n $parm_Submit ]]; then
379 X       saveIFS=$IFS
380 X       IFS='&;'
381 X       set -A flds -- $QUERY_STRING
382 X       IFS=$saveIFS
383 X
384 X       rm -rf data/groups/roles
385 X       for n in "${ldap_groups[@]}"; do
386 X               mkdir -p data/groups/roles/"$n"
387 X       done
388 X
389 X       for fld in "${flds[@]}"; do
390 X               k=${fld%%=*}
391 X               [[ $k = 'gr%5B%5D' || $k = 'gr%5b%5d' || $k = 'gr[]' ]] || continue
392 X               v=${fld#*=}
393 X               v=${v//+/ }
394 X               v=${v//\\/\\\\}
395 X               v=${v//[%]/\\x}
396 X               v=$(print -- "$v")
397 X               va=${v%/*}
398 X               vb=${v#*/}
399 X               [[ -d data/groups/roles/"$va"/. ]] || continue
400 X               for r in "${roles[@]}"; do
401 X                       [[ $r = "$vb" ]] || continue
402 X                       :>data/groups/roles/"$v"
403 X                       break
404 X               done
405 X       done
406 Xfi
407 X
408 Xhtml_open "Assign Roles to Groups"
409 Xprint '<form method="get" action="grprole.cgi">'
410 Xprint '<div><table border="1">'
411 Xprint '<tr>'
412 Xprint ' <th align="right">Group \ Role</th>'
413 Xfor r in "${roles[@]}"; do
414 X       print " <th>$r</th>"
415 Xdone
416 Xprint '</tr>'
417 Xfor n in "${ldap_groups[@]}"; do
418 X       mkdir -p data/groups/roles/"$n"
419 X       print '<tr>'
420 X       print " <th align=\"right\">$n</th>"
421 X       for r in "${roles[@]}"; do
422 X               print -n ' <td><input type="checkbox" name="gr[]" value="'"$n/$r"\"
423 X               [[ -e data/groups/roles/$n/$r ]] && print -n ' checked="checked"'
424 X               print " /></td>"
425 X       done
426 X       print '</tr>'
427 Xdone
428 Xprint '</table></div><div>'
429 Xprint '<p><input type="submit" name="Submit" value="Rollen zuweisen" /></p>'
430 Xprint '</div></form>'
431 Xhtml_close
432 Xexit 0
433 END-of-rechte-mock/grprole.cgi
434 echo x - rechte-mock/roleperm.cgi
435 sed 's/^X//' >rechte-mock/roleperm.cgi << 'END-of-rechte-mock/roleperm.cgi'
436 X#!/bin/mksh
437 X# $Id$
438 X#-
439 X# Copyright © 2011, 2012
440 X#      Thorsten “mirabilos” Glaser <t.glaser@tarent.de>
441 X# Licenced under the AGPLv3
442 X
443 X. "$(dirname "$0")"/common
444 X
445 X(cd data/roles; for n in *; do
446 X       [[ -s $n ]] && print -r -- "$n"
447 Xdone) |&
448 XIFS=$'\n' read -p -A -N-1 roles
449 X
450 Xparse_getparms Submit
451 Xif [[ -n $parm_Submit ]]; then
452 X       saveIFS=$IFS
453 X       IFS='&;'
454 X       set -A flds -- $QUERY_STRING
455 X       IFS=$saveIFS
456 X
457 X       allnull=
458 X       j=-1
459 X       while (( ++j < ${#perm_bits[*]} )); do
460 X               allnull+=' 0'
461 X       done
462 X
463 X       j=-1
464 X       for r in "${roles[@]}"; do
465 X               u=role_bits_$((++j))
466 X               eval set -A $u $allnull
467 X       done
468 X
469 X       for fld in "${flds[@]}"; do
470 X               k=${fld%%=*}
471 X               [[ $k = 'rp%5B%5D' || $k = 'rp%5b%5d' || $k = 'rp[]' ]] || continue
472 X               v=${fld#*=}
473 X               v=${v//+/ }
474 X               v=${v//\\/\\\\}
475 X               v=${v//[%]/\\x}
476 X               v=$(print -- "$v")
477 X               va=${v%,*}
478 X               vb=${v#*,}
479 X               [[ $va = +([0-9]) ]] || continue
480 X               (( va < 0 || va >= ${#perm_bits[*]} )) && continue
481 X               j=-1
482 X               for r in "${roles[@]}"; do
483 X                       u=role_bits_$((++j))
484 X                       [[ $r = "$vb" ]] || continue
485 X                       eval $u'[va]=1'
486 X                       break
487 X               done
488 X       done
489 X
490 X       j=-1
491 X       for r in "${roles[@]}"; do
492 X               u=role_bits_$((++j))
493 X               eval 'print ${'$u'[*]} >data/roles/"$r"'
494 X       done
495 Xfi
496 X
497 Xi=-1
498 Xfor n in "${perm_bits[@]}"; do
499 X       v=role_perm_$((++i))
500 X       eval set -A $v
501 X       j=0
502 X       for r in "${roles[@]}"; do
503 X               set -A cur_perms -- $(<data/roles/$r)
504 X               w=0
505 X               [[ ${cur_perms[i]} = *1* ]] && w=1
506 X               eval $v'[j++]=$w'
507 X       done
508 Xdone
509 X
510 Xhtml_open "Assign Permissions to Roles"
511 Xprint '<form method="get" action="roleperm.cgi">'
512 Xprint '<div><table border="1">'
513 Xprint '<tr>'
514 Xprint ' <th align="right">Permission \ Role</th>'
515 Xfor r in "${roles[@]}"; do
516 X       print " <th>$r</th>"
517 Xdone
518 Xprint '</tr>'
519 Xi=-1
520 Xfor n in "${perm_bits[@]}"; do
521 X       v=role_perm_$((++i))
522 X       print '<tr>'
523 X       print " <th align=\"right\">$n</th>"
524 X       j=0
525 X       for r in "${roles[@]}"; do
526 X               print -n ' <td><input type="checkbox" name="rp[]" value="'"$i,$r"\"
527 X               eval w='${'$v'[j++]}'
528 X               (( w )) && print -n ' checked="checked"'
529 X               print " /></td>"
530 X       done
531 X       print '</tr>'
532 Xdone
533 Xprint '</table></div><div>'
534 Xprint '<p><input type="submit" name="Submit" value="Rechte an Rollen zuweisen" /></p>'
535 Xprint '</div></form>'
536 Xhtml_close
537 Xexit 0
538 END-of-rechte-mock/roleperm.cgi
539 echo x - rechte-mock/se.cgi
540 sed 's/^X//' >rechte-mock/se.cgi << 'END-of-rechte-mock/se.cgi'
541 X#!/bin/mksh
542 X# $Id$
543 X#-
544 X# Copyright © Thorsten Glaser, taken from MirBSD with permission.
545 X
546 Xvars=$(set)
547 X#set -A args -- "$0" "$@"
548 X#opts=$(set -o)
549 X#set -o arc4random
550 Xprint Content-type: text/plain
551 X#print Entropy: $RANDOM
552 Xprint
553 Xinteger i=0
554 Xwhile (( i < ${#args[*]} )); do
555 X       print -r "ARGV[$i]=${args[i]}"
556 X       let i++
557 Xdone
558 Xprint -r -- "$vars"
559 Xprint -- ------------------------------------------------------------------------------
560 X#print -r -- "$opts"
561 X#print -- ------------------------------------------------------------------------------
562 Xif [[ $REQUEST_METHOD = POST ]]; then
563 X       cat
564 X       print
565 X       print -- ------------------------------------------------------------------------------
566 Xfi
567 Xexit 0
568 END-of-rechte-mock/se.cgi
569 exit