]> git.plutz.net Git - shellwiki/blob - handlers/20_attachment.sh
allow attachment revisioning
[shellwiki] / handlers / 20_attachment.sh
1 #!/bin/sh
2
3 . "$_EXEC/cgilite/file.sh"
4
5 attachment_convert(){
6   local attpath="$1"
7   local cachepath="${attpath%/#attachments/*}/#cache/${attpath#*/#attachments/}"
8   local res junk
9
10   case $attpath in
11     *.webm|*.mp4|*.mkv|*.avi)
12       cachepath="${cachepath}.webm"
13       ;;
14   esac
15
16   if [ -s "$cachepath" ]; then
17     printf %s "$cachepath"
18     return 0
19   elif [ -f "$cachepath" ]; then
20     printf %s "$attpath"
21     return 0
22   elif ! mkdir -p -- "${cachepath%/*}" && touch "$cachepath"; then
23     printf %s "$attpath"
24     return 0
25   fi
26
27   case $attpath in
28     *.jpg|*.jpeg|*.png)
29       read junk junk res junk <<-EOF
30         $(identify "$attpath")
31         EOF
32       if [ "${res%x*}" -gt 2048 ]; then
33         convert "$attpath" -resize 1920x-2 -quality 85 "$cachepath"
34       else
35         convert "$attpath" -quality 85 "$cachepath"
36       fi
37       printf %s "$cachepath"
38       return 0
39     ;;
40     *.webm|*.mp4|*.mkv|*.avi)
41       res=$(ffprobe -show_entries stream=width "$attpath" 2>&-)
42       res="${res#*width=}" res="${res%%${BR}*}"
43       if [ "$res" -gt 1280 ]; then
44         ( exec >&- 2>&1;
45           ffmpeg -y -nostdin -i "$attpath" \
46           -c:v libvpx -vf scale=1280:-2 -crf 28 -b:v 0 \
47           -c:a libvorbis -q:a 6 \
48           "${cachepath%.*}.tmp.webm" \
49           && mv -- "${cachepatch%.*}.tmp.webm" "${cachepath}" \
50         & ) &
51        
52       else
53         ( exec >&- 2>&1;
54           ffmpeg -y -nostdin -i "$attpath" \
55           -c:v libvpx -crf 28 -b:v 0 \
56           -c:a libvorbis -q:a 6 \
57           "${cachepath%.*}.tmp.webm" \
58           && mv -- "${cachepatch%.*}.tmp.webm" "${cachepath}" \
59         & ) &
60       fi
61       printf %s "$attpath"
62       return 0
63     ;;
64     *) printf "$attpath";;
65   esac
66 }
67
68 case ${PATH_INFO} in
69   */\[attachment\]/)
70     # no trailing slash
71     REDIRECT "${_BASE}${PATH_INFO%/}"
72     ;;
73   */*/)
74     # attached files never end on /
75     return 1
76     ;;
77   */\[attachment\])
78     # show attachment page
79     # receive uploads
80     tsid="$(POST session_key)"; tsid="${tsid%% *}"
81     attachment_delete="$(POST delete)"
82     page="${PATH_INFO%\[attachment\]}"
83
84     if [ ! -d "$_DATA/pages${page}" -a ! -d "$_DATA/pages${page}" ]; then
85       # base page does not exist
86       return 1
87     elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ] && acl_write "${page}"; then
88       . "$_EXEC/multipart.sh"
89       multipart_cache
90
91       # Validate session id from form to prevent CSRF
92       # Only validate if username is present, because no username means
93       # anonymous uploads are allowed via acl and cgilite/session.sh does not
94       # validate anonymous sessions from a multipart/formdata
95       if [ "$USER_NAME" -a "$(multipart session_id)" != "$SESSION_ID" ]; then
96         rm -- "$multipart_cachefile"
97         printf 'Refresh: %i\r\n' 4
98         theme_error 403
99         return 0
100       fi
101
102       mkdir -p "$_DATA/pages${page}#attachments/"
103       n=1; while filename=$(multipart_filename "file" "$n"); do
104         filename="$(printf %s "$filename" |tr /\\0 __)"
105         multipart "file" "$n" >"$_DATA/pages${page}#attachments/$filename"
106         n=$((n + 1))
107       done
108       rm -- "$multipart_cachefile"
109       REDIRECT "${_BASE}${PATH_INFO}"
110     elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ]; then
111       printf 'Refresh: %i\r\n' 4
112       theme_error 403
113       head -c $((CONTENT_LENGTH)) >/dev/null
114       return 0
115     elif [ "$attachment_delete" -a "$SESSION_ID" = "$tsid" ]; then
116       rm -- "$_DATA/pages${page}#attachments/$attachment_delete"
117       REDIRECT "${_BASE}${PATH_INFO}"
118     elif [ "$attachment_delete" ]; then
119       printf 'Refresh: %i\r\n' 4
120       theme_error 403
121       return 0
122     elif ! acl_read "${page}"; then
123       theme_error 403
124       return 0
125     else
126       theme_attachments "${page}"
127       return 0
128     fi
129     ;;
130
131   */\[attachment\]/*)
132     attpath="${PATH_INFO%/\[attachment\]/*}/#attachments/${PATH_INFO##*/}"
133
134     if [ ! -f "$_DATA/pages/$attpath" -a ! -f "$_EXEC/pages/$attpath" ]; then
135       return 1
136     elif ! acl_read "${PATH_INFO%/\[attachment\]/*}"; then
137       theme_error 403
138       return 0
139     elif [ -f "$_DATA/pages/$attpath" ]; then
140       FILE "$_DATA/pages/$attpath"
141       return 0
142     elif [ -f "$_EXEC/pages/$attpath" ]; then
143       FILE "$_EXEC/pages/$attpath"
144       return 0
145     fi
146     ;;
147   */*)
148     attpath="${PATH_INFO%/*}/#attachments/${PATH_INFO##*/}"
149
150     if [ ! -f "$_DATA/pages/$attpath" -a ! -f "$_EXEC/pages/$attpath" ]; then
151       return 1
152     elif ! acl_read "${PATH_INFO%/*}/"; then
153       theme_error 403
154       return 0
155     elif [ -f "$_DATA/pages/$attpath" ]; then
156       FILE "$(attachment_convert "$_DATA/pages/$attpath")"
157       return 0
158     elif [ -f "$_EXEC/pages/$attpath" ]; then
159       FILE "$(attachment_convert "$_EXEC/pages/$attpath")"
160       return 0
161     fi
162     ;;
163 esac
164
165 return 1