dirty fix: do not mess up with empty tags
[confetti] / pages / cards.sh
1 #!/bin/zsh
2
3 # Copyright 2014 - 2016 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 BR='
21 '
22
23 case $PROFILE in
24 medical)
25   view_card="$_EXEC/templates/view_client.sh"
26   edit_card="$_EXEC/templates/edit_client.sh"
27   _GET[order]="${_GET[order]:-lastname}"
28   _GET[filtertype]="${_GET[filtertype]:-name}"
29   profile_medical=x
30 ;;
31 circus)
32   view_card="$_EXEC/templates/view_attendee.sh"
33   edit_card="$_EXEC/templates/edit_attendee.sh"
34   _GET[order]="${_GET[order]:-firstname}"
35   _GET[filtertype]="${_GET[filtertype]:-any}"
36   profile_circus=x
37 ;;
38 esac
39
40 edit="${_GET[edit]}"
41 [ \! -f "vcard/$edit" -a \! -f "temp/$edit" ] && edit=''
42
43 listcourses() {
44   ls -1 ${_DATA}/ical/*ics |while read file; do
45     icstime="$(sed -rn 's:^DTSTART\:(TZID=.*\:)?([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2})([0-9]{2})([0-9]{2})Z?\r$:\2-\3-\4 \5\:\6\:\7:p' "$file")"
46     echo "$(date -d "$icstime" "+%u %H%M%S")\t$file"
47   done |sort |sed -r 's:^.*\t(.*/)([^/]+)$:\2:'
48 }
49
50 list_hi_companies(){
51   sed -rn 's;^X-HEALTH-INSURANCE:([^\;]+)\;.*$;\1;p' ${_DATA}/vcard/*vcf \
52   | sort -u
53 }
54
55 listcards() {
56   case "${_GET[filtertype]}" in
57     any)
58        grep -il "${_GET[filter]}" ${_DATA}/vcard/*vcf
59       ;;
60     name)
61        egrep -xil "(FN|NICKNAME|N)(;.+)*:.*${_GET[filter]}.*" ${_DATA}/vcard/*vcf
62       ;;
63     street)
64        egrep -xil "(ADR)(;.+)*:([^;]*;){2}${_GET[filter]}.*" ${_DATA}/vcard/*vcf
65       ;;
66     zip)
67        egrep -xil "(ADR)(;.+)*:([^;]*;){5}${_GET[filter]}.*" ${_DATA}/vcard/*vcf
68       ;;
69     telephone)
70        egrep -xil "(TEL)(;.+)*:.*${_GET[filter]}.*" ${_DATA}/vcard/*vcf
71       ;;
72     birth)
73        egrep -xil "(BDAY)(;.+)*:${_GET[filter]}.*" ${_DATA}/vcard/*vcf
74       ;;
75     course)
76       ;;
77     *) ls -1 ${_DATA}/vcard/*vcf 2>/dev/null
78       ;;
79   esac |case "${_GET[order]}" in
80     firstname)
81       while read file; do
82         fn=$(sed -rn 's:^N(;.+)*\:([^;]*;){1} *([^;]*).*$:\3:p' "$file")
83         echo "$fn\t$file"
84       done
85       ;;
86     lastname)
87       while read file; do
88         ln=$(sed -rn 's:^N(;.+)*\:([^;]*;){0} *([^;]*).*$:\3:p' "$file")
89         echo "$ln\t$file"
90       done
91       ;;
92     bdate)
93       while read file; do
94         bd=$(sed -rn 's:^BDAY(;.+)*\:(.*)$:\2:p' "$file")
95         echo "$bd\t$file"
96       done
97       ;;
98     *)
99       sed -r 's:^.*$:x\t&:'
100       ;;
101   esac |sort |sed -r 's:^.*\t(.*/)([^/]+)$:\2:'
102 }
103
104 vcf_parse() {
105   tr -d '\n' <"$1" |sed -r 's:\r ::g;s:\r:\n:g' \
106   | sed -rn '
107     s:^X-MS-CARDPICTURE:PHOTO:p;
108     s:^X-GENDER:GENDER:p;
109     s:^X-ANNIVERSARY:ANNIVERSARY:p;
110     s:^X-EVOLUTION-ANNIVERSARY:ANNIVERSARY:p;
111     s:^X-KADDRESSBOOK-X-Anniversary:ANNIVERSARY:p;
112     s:^X-AIM(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:aim\:\2:p;
113     s:^X-ICQ(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:aim\:\2:p;
114     s:^X-GOOGLE-TALK(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:xmpp\:\2:p;
115     s:^X-JABBER(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:xmpp\:\2:p;
116     s:^X-MSN(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:msn\:\2:p;
117     s:^X-YAHOO(;[^"\:]+|;"[^"]+")*\:(.*)$:IMPP\1\:ymsgr\:\2:p;
118     s:^X-SIP(;[^"\:]+|;"[^"]+")*\:(sip\:)?(.*)$:IMPP\1\:sip\:\3:p;
119     s:^LABEL(;[^"\:]+|;"[^"]+")*\:(.*)$:ADR;LABEL="\2"\1\::p;
120     s:^X-EVOLUTION-BLOG-URL:URL:p;
121
122     s:^AGENT:RELATED\;TYPE=agent:p;
123     s:^X-ASSISTANT:RELATED\;TYPE=assistant;VALUE=text:p;
124     s:^X-EVOLUTION-ASSISTANT:RELATED\;TYPE=assistant;VALUE=text:p;
125     s:^X-KADDRESSBOOK-X-AssistantsName:RELATED\;TYPE=assistant;VALUE=text:p;
126     s:^X-MANAGER:RELATED\;TYPE=manager;VALUE=text:p;
127     s:^X-EVOLUTION-MANAGER:RELATED\;TYPE=manager;VALUE=text:p;
128     s:^X-KADDRESSBOOK-X-ManagersName:RELATED\;TYPE=manager;VALUE=text:p;
129     s:^X-SPOUSE:RELATED\;TYPE=spouse;VALUE=text:p;
130     s:^X-EVOLUTION-SPOUSE:RELATED\;TYPE=spouse;VALUE=text:p;
131     s:^X-KADDRESSBOOK-X-SpouseName:RELATED\;TYPE=spouse;VALUE=text:p;
132
133     s:^([A-Z].*)$:\1:p;
134     ' \
135   | sed -r 's:^([^;\:]+)(;[^"\:]+|;"[^"]+")*\:(.*)$:key="\1"\nvalue="\3"\ntag=\2:g' \
136   | while read -r line; do
137     case "$line" in
138       key=*) printf %s\\n "$line"
139         ;;
140       value=*) printf %s\\n "${line}"
141         ;;
142       tag=*) ot=''
143              printf %s "$line" \
144              | sed -r 's:^tag=::;s:\;([A-Z+_-]+="[^"]+"|[A-Z+_-]+=[^\;]+):\n\1:g;' \
145              | sed -rn 's:([A-Z+_-]+)="?(.+)"?:tag\[\1\]="\2":gp' \
146              | sed -r '/^ *$/d' \
147              | sort |while read -r tag; do
148                nt="$(printf %s "$tag" |sed -r 's:^tag\[([A-Z+_-]+)\]="(.*)"$:\1:')"
149                nv="$(printf %s "$tag" |sed -r 's:^tag\[([A-Z+_-]+)\]="(.*)"$:\2:')"
150                [ "$nt" = "$ot" ] && vl="$nv,$vl" || vl="$nv"
151                printf %s\\n "tag[$nt]=\"$vl\""
152                ot="$nt"
153              done
154         ;;
155     esac
156   done \
157   | sed -r 's:[\\$`]:\\&:g'
158 }
159
160 view_card() {  #Parameter: Cardfile
161   id="$1"
162   cardfile="$_DATA/vcard/${id}"
163   cachefile="$_DATA/cache/${id}.cache"
164   unset key
165   if [ "$cachefile" -nt "$cardfile" ]; then
166     cat "$cachefile"
167   else
168     declare -A tags
169     declare -A values
170     vcf_parse "$cardfile" |while read -r line; do
171       declare -A tag
172       case "$line" in
173         value*) eval "$line";;
174         tag*)   eval "$line";;
175         key*)
176           if [ -z "$key" ]; then
177             eval "$line"
178           else
179             values[$key]="${value//\\r\\n/$BR}"
180             for t in ${(k)tag}; do
181               tags[${key}_$t]="$tag[$t]"
182             done
183             eval "$line"
184             if [ -n "$values[$key]" ]; then
185               n=0
186               while [ -n "$values[$key$n]" ]; do n=$(($n + 1)); done
187               key=$key$n
188             fi
189             unset value
190             unset tag
191           fi
192         ;;
193       esac
194     done
195     . $view_card |tee "$cachefile"
196   fi
197 }
198
199 edit_card() {  #Parameter: Cardfile
200   id="$1"
201   cardfile="$_DATA/vcard/$id"
202   tempfile="$_DATA/temp/$id"
203   [ -f "$tempfile" ] && cardfile="$tempfile"
204   unset key
205
206   declare -A tags
207   declare -A values
208   vcf_parse "$cardfile" |while read -r line; do
209     declare -A tag
210     case "$line" in
211       value*) eval "$line";;
212       tag*)   eval "$line";;
213       key*)
214         if [ -z "$key" ]; then
215           eval "$line"
216         else
217           [ -n "$value" ] && values[$key]="${value//\\r\\n/$BR}" || values[$key]='\r'
218           for t in ${(k)tag}; do
219             tags[${key}_$t]="$tag[$t]"
220           done
221           eval "$line"
222           if [ -n "$values[$key]" ]; then
223             n=0
224             while [ -n "$values[${key}${n}]" ]; do n=$(($n + 1)); done
225             key=$key$n
226           fi
227             unset value
228             unset tag
229         fi
230       ;;
231     esac
232   done
233   . $edit_card
234 }