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