]> git.plutz.net Git - confetti/blobdiff - pages/cards.sh
unification of card editing functions
[confetti] / pages / cards.sh
index 0ead803fb32304a581ba5fcdaae35bcd2e8413de..2d1d4e29e112c825e6e5652e50e44bf5ca0a2d31 100755 (executable)
 BR='
 '
 
+force_items(){
+  for each in "$@"; do
+    [ -z "${values[$each]+x}" ] && values[${each}]=''
+  done
+}
+
 case $PROFILE in
 medical)
+  SUP_FIELDS=(N NICKNAME GENDER BDAY ADR TEL EMAIL X-HEALTH-INSURANCE X-HEALTH-INSURANCE-NOCONTRIB IMPP URL NOTE X-CLIENT-REFERRAL)
+  FORCE_ITEMS=(ADR TEL EMAIL NOTE X-CLIENT-REFERRAL)
   view_card="$_EXEC/templates/view_client.sh"
   edit_card="$_EXEC/templates/edit_client.sh"
   _GET[order]="${_GET[order]:-lastname}"
@@ -29,6 +37,8 @@ medical)
   profile_medical=x
 ;;
 circus)
+  SUP_FIELDS=(N NICKNAME GENDER BDAY X-ZACK-JOINDATE X-ZACK-LEAVEDATE EMAIL TEL IMPP ADR URL NOTE)
+  FORCE_ITEMS=(BDAY X-ZACK-JOINDATE TEL EMAIL ADR NOTE)
   view_card="$_EXEC/templates/view_attendee.sh"
   edit_card="$_EXEC/templates/edit_attendee.sh"
   _GET[order]="${_GET[order]:-firstname}"
@@ -102,14 +112,18 @@ listcards() {
 }
 
 vcf_parse() {
+  unset key
   sed -r ':X;N;$!bX; s;\r\n[ \t];;g; s;\r\n;\n;g;' "$1" \
   | sed -rn '
-    # === turn property names to upper case ===
-    h; s;^([^\;:]+);;;
-    x; s;^([^\;:]+).*$;\1;;
+    # === turn property names to upper case, strip group names ===
+    h; s;^([^;:]+);;;
+    x; s;^([^;:\.]+\.)?([^;:]+).*$;\2;;
     y;abcdefghijklmnopqrstuvwxyz;ABCDEFGHIJKLMNOPQRSTUVWXYZ;
     G; s;\n;;;
 
+    # === strip trailing CR (but keep CRs in property value) ===
+    s;\r$;;;
+
     # === Normalise various known vendor properties ===
                 s;^X-MS-CARDPICTURE(\;|:);PHOTO\1;;
                         s;^X-GENDER(\;|:);GENDER\1;;
@@ -129,73 +143,119 @@ vcf_parse() {
         s;^X-KADDRESSBOOK-X-SPOUSENAME(\;|:);RELATED\;VALUE=text\;TYPE=spouse\1;;
 
     # === Normalise obsolete vendor IM properties ===
-            s;^X-AIM((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:aim:;;
-            s;^X-ICQ((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:aim:;;
-    s;^X-GOOGLE-TALK((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:xmpp:;;
-         s;^X-JABBER((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:xmpp:;;
-            s;^X-MSN((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:msn:;;
-          s;^X-YAHOO((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):;IMPP\1:ymsgr:;;
-            s;^X-SIP((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):(sip:)?;IMPP\1:sip:;;
+            s;^X-AIM((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:aim:;;
+            s;^X-ICQ((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:aim:;;
+    s;^X-GOOGLE-TALK((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:xmpp:;;
+         s;^X-JABBER((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:xmpp:;;
+            s;^X-MSN((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:msn:;;
+          s;^X-YAHOO((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):;IMPP\1:ymsgr:;;
+            s;^X-SIP((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):(sip:)?;IMPP\1:sip:;;
 
     # === Update obsolete LABEL property ===
-    s;^LABEL((\;[a-zA-Z0-9-]+|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):(.*)$;ADR\1\;LABEL="\5":;;
+    s;^LABEL((\;[a-Z0-9-]+|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):(.*)$;ADR\1\;LABEL="\5":;;
 
-    /^([a-zA-Z0-9-]+)((\;[a-zA-Z0-9-]+=?|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):(.*)$/{
+    /^([A-Z0-9-]+)((\;[a-Z0-9-]+=?|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):(.*)$/{
       h;
-      s;^([a-zA-Z0-9-]+)((\;[a-zA-Z0-9-]+=?|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):(.*)$;key='\''\1'\'';;
+      s;^([A-Z0-9-]+)((\;[a-Z0-9-]+=?|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):(.*)$;key='\''\1'\'';;
       H; g;
-      s;^([a-zA-Z0-9-]+)((\;[a-zA-Z0-9-]+=?|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):([^\n]*)\n.*$;\6;;
+
+      s;^([A-Z0-9-]+)((\;[a-Z0-9-]+=?|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):([^\n]*)\n.*$;\2;;
       s;'\'';'\'\\\\\'\'';g
-      s;^.*$;value='\''&'\'';
-      H; g;
-      s;^([a-zA-Z0-9-]+)((\;[a-zA-Z0-9-]+=?|\;[a-zA-Z0-9-]+=([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*)*):([^\n]*)\n.*$;\2;;
+      s;\;([A-Z0-9-]+)(=|=(([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*))?;\ntag[\1]='\''\3'\'';g
+      s;^\n+;;; s;\n+$;;;
+      /^.+$/H; g;
+
+      s;^([A-Z0-9-]+)((\;[a-Z0-9-]+=?|\;[a-Z0-9-]+=([^;,:"]+|"[^"]+")(,[^;,:"]+|,"[^"]+")*)*):([^\n]*)\n.*$;\6;;
+      # :X s;((^|[^\\])(\\\\)*)[;,];\1\n;g; s;((^|[^\\])(\\\\)*)\\([;,]);\4;g; tX;
       s;'\'';'\'\\\\\'\'';g
-      s;\;([a-zA-Z0-9-]+)(=|=(([^\;,:"]+|"[^"]+")(,[^\;,:"]+|,"[^"]+")*))?;\ntag[\1]='\''\3'\'';g
+      s;^.*$;value='\''&'\'';
       H; g;
-      s;^[^\n]*[\n ]+;;
 
-      s;\n[\n ]+;\n;g; s;\n$;;;
+      s;^[^\n]*[\n ]+;;
+      s;\n+$;;;
 
       p;
     }
-    '
+    ' \
+  | while read -r line; do
+    declare -A tag
+    case "$line" in
+      value*) eval "$line";;
+      tag*)   eval "$line";;
+      key*)
+        if [ -z "$key" ]; then
+          eval "$line"
+        else
+          printf '%s\n' "$value" |sed -rn '
+            :X
+            s;((^|[^\\])(\\\\)*),;\1\n;g; 
+            tX;
+            s;\\,;,;g;
+            p
+          ' \
+          | while read -r val; do
+            while [ -n "${values[$key$n]+x}" ]; do n=$((${n=-1} + 1)); done
+            if printf '%s\n' "$val" |grep -qE '((^|[^\\])(\\\\)*)\;'; then
+              m=0
+              values[${key}${n}]="${val}"
+              printf '%s\n' "$val" |sed -rn '
+                :X
+                s;((^|[^\\])(\\\\)*)\;;\1\n;g; 
+                tX;
+                s;\\\;;\;;g;
+                p
+              ' \
+              | while read -r v; do
+                values[${key}${n}+${m}]="$(
+                  printf %s\\n "${v}" \
+                  | sed -rn '
+                    :X
+                    s;((^|[^\\])(\\\\)*)\\n;\1\n;g; 
+                    tX;
+                    s;\\\\;\\;g;
+                    p
+                  '
+                )"
+                m=$(($m + 1))
+              done
+            else
+              values[${key}${n}]="$(
+                printf %s\\n "${val}" \
+                | sed -rn '
+                  :X
+                  s;((^|[^\\])(\\\\)*)\\n;\1\n;g; 
+                  tX;
+                  s;\\\;;\;;g;
+                  s;\\\\;\\;g;
+                  p
+                '
+              )"
+            fi
+            for t in ${(k)tag}; do
+              values[${key}${n}_${t}]="${tag[$t]}"
+            done
+          done
+
+          eval "$line"
+          unset n
+          while [ -n "${values[$key$n]+x}" ]; do n=$((${n=-1} + 1)); done
+          unset value
+          unset tag
+        fi
+      ;;
+    esac
+  done
 }
 
 view_card() {  #Parameter: Cardfile
   id="$1"
   cardfile="$_DATA/vcard/${id}"
   cachefile="$_DATA/cache/${id}.cache"
-  unset key
   if [ "$cachefile" -nt "$cardfile" ]; then
     cat "$cachefile"
   else
-    declare -A tags
     declare -A values
-    vcf_parse "$cardfile" |while read -r line; do
-      declare -A tag
-      case "$line" in
-        value*) eval "$line";;
-        tag*)   eval "$line";;
-        key*)
-          if [ -z "$key" ]; then
-            eval "$line"
-          else
-            values[$key]="${value//\\r\\n/$BR}"
-            for t in ${(k)tag}; do
-              tags[${key}_$t]="$tag[$t]"
-            done
-            eval "$line"
-            if [ -n "$values[$key]" ]; then
-              n=0
-              while [ -n "$values[$key$n]" ]; do n=$(($n + 1)); done
-              key=$key$n
-            fi
-            unset value
-            unset tag
-          fi
-        ;;
-      esac
-    done
+    vcf_parse "$cardfile"
     . $view_card |tee "$cachefile"
   fi
 }
@@ -205,34 +265,9 @@ edit_card() {  #Parameter: Cardfile
   cardfile="$_DATA/vcard/$id"
   tempfile="$_DATA/temp/$id"
   [ -f "$tempfile" ] && cardfile="$tempfile"
-  unset key
 
-  declare -A tags
   declare -A values
-  vcf_parse "$cardfile" |while read -r line; do
-    declare -A tag
-    case "$line" in
-      value*) eval "$line";;
-      tag*)   eval "$line";;
-      key*)
-        if [ -z "$key" ]; then
-          eval "$line"
-        else
-          [ -n "$value" ] && values[$key]="${value//\\r\\n/$BR}" || values[$key]='\r'
-          for t in ${(k)tag}; do
-            tags[${key}_$t]="$tag[$t]"
-          done
-          eval "$line"
-          if [ -n "$values[$key]" ]; then
-            n=0
-            while [ -n "$values[${key}${n}]" ]; do n=$(($n + 1)); done
-            key=$key$n
-          fi
-            unset value
-            unset tag
-        fi
-      ;;
-    esac
-  done
+  vcf_parse "$cardfile"
+  force_items $FORCE_ITEMS
   . $edit_card
 }