implement course edit and updates
[confetti] / courses / update_course.sh
1 #!/bin/zsh
2
3 # Copyright 2014, 2015, 2020 Paul Hänsch
4 #
5 # This file is part of Confetti.
6
7 # Confetti is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # Confetti is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU Affero General Public License for more details.
16
17 # You should have received a copy of the GNU Affero General Public License
18 # along with Confetti.  If not, see <http://www.gnu.org/licenses/>. 
19
20 . "$_EXEC/pdiread.sh"
21 . "$_EXEC/session_lock.sh"
22 . "$_EXEC/cgilite/storage.sh"
23
24 unset coursefile attfile tempfile
25
26 course="$(POST course |PATH)"; course="${course##*/}"
27 coursefile="$_DATA/ical/$course"
28 attfile="$_DATA/mappings/attendance"
29
30 action="$(POST action)"
31 newfield="$(POST newfield |grep -m 1 -xE '[A-Z][A-Z0-9-]*')"
32
33 if printf '%s\n' "$action" |grep -qxE 'addfield [A-Z][A-Z0-9]*'; then
34   newfield="${action##* }"
35   action=addfield
36 fi
37
38 if ! tempfile="$(CHECK_SLOCK "$coursefile")"; then
39   SET_COOKIE 0 message="NO VALID FILE LOCK"
40   REDIRECT "/courses/?e=${course}"
41   exit 0
42 elif [ "$(POST tid)" != "$(transid "$tempfile")" ]; then
43   SET_COOKIE 0 message="INVALID TRANSACTION ID"
44   REDIRECT "/courses/?e=${course}"
45   exit 0
46 fi
47
48 vcf_escape(){
49   for each in "$@"; do
50     printf %s\\n "$each" \
51     | sed -E ':X;$!{N;bX}; s;\r\n;\n;g; s;([;,\\]);\\\1;g; s;\n;\\n;g;'
52   done \
53   | sed -E ':X;$!{N;bX}; s;\n;\;;g'
54 }
55
56 course="$(pdi_load "$coursefile")"
57
58 tzid=$(cat /etc/timezone)
59
60 course="$(pdi_update_attrib "$course" DTSTAMP 1 "TZID=${tzid}")"
61 course="$(pdi_update_value  "$course" DTSTAMP 1 "$(TZ="$tzid" date +%Y%m%dT%H%M%S)")"
62
63 dts_year="$(  POST DTS_YEAR    |grep -m1 -xE '[0-9]{4}' || date +%Y)"
64 dts_month="$( POST DTS_MONTH   |grep -m1 -xE '0[1-9]|1[012]' || date +%m)"
65 dts_day="$(   POST DTS_DAY     |grep -m1 -xE '0[1-9]|[12][0-9]|3[01]' || date +%d)"
66 dts_hour="$(  POST DTS_HOUR    |grep -m1 -xE '[0-9]|1[0-9]|2[0-3]' || date +%H)"
67 dts_minute="$(POST DTS_MINUTE  |grep -m1 -xE '[0-9]|[1-5][0-9]' || date +%M)"
68 [ ${#dts_hour}   -eq 1 ] && dts_minute="0$dts_hour"
69 [ ${#dts_minute} -eq 1 ] && dts_minute="0$dts_minute"
70 DTSTART="${dts_year}${dts_month}${dts_day}T${dts_hour}${dts_minute}00"
71
72 course="$(pdi_update_attrib "$course" DTSTART 1 "TZID=${tzid}")"
73 course="$(pdi_update_value  "$course" DTSTART 1 "$DTSTART")"
74
75 rr_int=$(  POST RRULE_INTERVAL |grep -m1 -xE '[0-9]+' || printf 1)
76 rr_count=$(POST RRULE_COUNT    |grep -m1 -xE '[0-9]+' || printf 1)
77 rr_freq=$( POST RRULE_FREQ     |grep -m1 -xE 'DAILY|WEEKLY|MONTHLY|YEARLY' || printf MONTHLY)
78 rr_uy=$(   POST RRULE_UYEAR    |grep -m1 -xE '[0-9]{4}' || date +%Y)
79 rr_um=$(   POST RRULE_UMONTH   |grep -m1 -xE '[1-9]|1[012]' || date +%m)
80 rr_ud=$(   POST RRULE_UDAY     |grep -m1 -xE '[1-9]|[12][0-9]|3[01]' || date +%d)
81 [ ${#rr_um} -eq 1 ] && rr_um="0$rr_um"
82 [ ${#rr_ud} -eq 1 ] && rr_ud="0$rr_ud"
83
84 case $(POST RRULE_LIMIT) in
85   COUNT)   RRULE="FREQ=$rr_freq;INTERVAL=$rr_int;COUNT=$rr_count";;
86   UNTIL)   RRULE="FREQ=$rr_freq;INTERVAL=$rr_int;UNTIL=${rr_uy}${rr_um}${rr_ud}T000000Z";;
87   ETERN|*) RRULE="FREQ=$rr_freq;INTERVAL=$rr_int";;
88 esac
89
90 course="$(pdi_update_value  "$course" RRULE 1 "$RRULE")"
91
92 for field in $(POST_KEYS |grep -xE '[A-Z][A-Z0-9-]*'); do
93   for cnt in $(seq 1 $(POST_COUNT "$field")); do
94     case "$field" in
95       *)
96          course="$(pdi_update_value "$course" "$field" "$cnt" "$(vcf_escape "$(POST "$field" "$cnt")")")"
97         ;;
98     esac
99 done; done
100
101 # delete fields, first mark for deletion using delete_key
102 # this way the field enumeration is preserved during the process
103 # finally filter marked lines
104 delete_key="$(randomid)"
105 for delete in $(POST_KEYS |grep -xE '[A-Z][A-Z0-9-]*_delete_[0-9]+'); do
106   f="${delete%%_*}"; c="${delete##*_}";
107   [ "$(POST "$delete")" = "true" ] && course="$(pdi_update_value "$course" "$f" "$c" "delete=${delete_key}")"
108 done
109 course="$(printf '%s\n' "$course" |sed -E "/^[^:]+:delete=${delete_key}\$/d")"
110
111 case "$(POST action)" in
112   addfield)
113     course="$(pdi_update_value "$course" "$newfield" $(( $(pdi_count "$course" "$newfield") + 1 )) '')"
114     printf '%s' "$course" |grep -vx '' >"$tempfile"
115     REDIRECT "/courses/?e=${course}"
116     ;;
117   update)
118     if LOCK "$attfile"; then
119       grep -F "${course}        " "$attfile" |while read junk card; do
120         touch "$_DATA/vcard/${card}"
121       done
122       sed -i -r "/^${course}    .+\$/d" "$attfile"
123       seq 1 $(POST_COUNT attendance) |while read n; do
124         printf '%s      %s\n' "$course" "$(POST attendance $n)"
125       done >>"$attfile"
126       grep -F "${course}        " "$attfile" |while read junk card; do
127         touch "$_DATA/vcard/${card}"
128       done
129       RELEASE "$attfile"
130     else
131       SET_COOKIE 0 message="COULD NOT UPDATE COURSE MAPPINGS"
132     fi
133
134     printf '%s' "$course" |grep -vx '' >"${tempfile}.cp"
135     mv "${tempfile}.cp" "$coursefile"
136     RELEASE_SLOCK "$coursefile"
137     REDIRECT "/courses/#${course}"
138     ;;
139   cancel)
140     RELEASE_SLOCK "$coursefile"
141     [ -f "$coursefile" ] \
142     && REDIRECT "/courses/#${course}" \
143     || REDIRECT "/courses/"
144     ;;
145   delete)
146     rm "$coursefile"
147     RELEASE_SLOCK "$coursefile"
148     REDIRECT "/courses/"
149     ;;
150 esac