]> git.plutz.net Git - shellwiki/blob - handlers/40_edit_attachment.sh
Merge commit '43ef03d4091027465dca65bca2ec6e4c52fbdff8'
[shellwiki] / handlers / 40_edit_attachment.sh
1 #!/bin/sh
2
3 REV_ATTACHMENTS="${REV_ATTACHMENTS:-false}"
4
5 if [ "${PATH_INFO##*/\[attachment\]}" ]; then
6   # Skip any action not happening on attachment page
7   return 1
8 fi
9
10 page="${PATH_INFO%\[attachment\]}"
11 action="$(POST action)"
12
13 tsid="$(POST session_key)"; tsid="${tsid%% *}"
14
15
16 if ! acl_write "${PATH_INFO%\[attachment\]}"; then
17   # Deny access to write protected pages
18   printf 'Refresh: %i\r\n' 4
19   theme_error 403
20   [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ] \
21   && head -c $((CONTENT_LENGTH)) >/dev/null
22   return 0
23
24 elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ]; then
25   . "$_EXEC/multipart.sh"
26   multipart_cache
27
28   # Use positional parameters for filename collection
29   # The positional array is the only array available
30   # in plain posix shells, see the documentation for
31   # your shells "set" builtin for a hint to this
32   # obscure use mode
33   set --
34
35   # Validate session id from form to prevent CSRF
36   # Only validate if username is present, because no username means
37   # anonymous uploads are allowed via acl and cgilite/session.sh does not
38   # validate anonymous sessions from a multipart/formdata
39   if [ "$USER_NAME" -a "$(multipart session_id)" != "$SESSION_ID" ]; then
40     rm -- "$multipart_cachefile"
41     printf 'Refresh: %i\r\n' 4
42     theme_error 403
43     return 0
44   fi
45
46   mkdir -p "$_DATA/pages${page}#attachments/"
47   n=1; while filename=$(multipart_filename "file" "$n"); do
48     filename="$(printf %s "$filename" |tr /\\0 __)"
49     set -- "$@" "pages${page}#attachments/$filename"
50     multipart "file" "$n" >"$_DATA/pages${page}#attachments/$filename"
51     n=$((n + 1))
52   done
53   rm -- "$multipart_cachefile"
54   if [ "$REV_ATTACHMENTS" = true ]; then
55     git -C "$_DATA" add -- "$@"
56     git -C "$_DATA" commit -qm "Attachments to # $page # uploaded by @ $USER_NAME @" -- "$@"
57   fi
58   REDIRECT "${_BASE}${PATH_INFO}"
59
60 elif [ "$SESSION_ID" != "$tsid" ]; then
61   # Match session key from POST-Data to prevent CSRF:
62   # For authenticated users the POST session_key must match
63   # the session key used for authentication (usually from a
64   # cookie). This should ensure that POST requests were not
65   # triggered by malicious 3rd party sites freeriding on an
66   # existing user authentication.
67   # For pages that are writable by anonymous users, this is
68   # not reliable.
69
70   printf 'Refresh: %i\r\n' 4
71   theme_error 403
72   return 0
73 fi
74
75 if [ "$action" = delete -o "$action" = move ]; then
76   set --
77   n="$(POST_COUNT select)"; while [ $n -gt 0 ]; do
78     select="$(POST select $n |PATH)"
79     set -- "$@" "pages${page}#attachments/${select##*/}"
80     n=$((n - 1))
81   done
82 fi
83
84 if [ "$action" = delete ]; then
85   if [ "$REV_ATTACHMENTS" = true ]; then
86     git -C "$_DATA" rm -- "$@"
87     git -C "$_DATA" commit -qm \
88         "Attachment to # $page # deleted by @ $USER_NAME @" -- "$@"
89   else
90     ( cd "$_DATA" && rm -- "$@"; )
91   fi
92   REDIRECT "${_BASE}${PATH_INFO}"
93
94 elif [ "$action" = move ]; then
95   moveto="$(POST moveto |PATH)"
96
97   if ! acl_write "$moveto"; then
98     printf 'Refresh: %i\r\n' 4
99     theme_error 403
100     return 0
101
102   elif [ ! -d "${_DATA}/pages${moveto}" ]; then
103     printf 'Refresh: %i\r\n' 4
104     theme_error 404
105     return 0
106
107   elif [ "$REV_ATTACHMENTS" = true ]; then
108     mkdir -p -- "${_DATA}/pages${moveto}/#attachments"
109     git -C "$_DATA" mv -f -- "$@" "pages${moveto}/#attachments/"
110
111     cnt=$#; while [ $cnt -gt 0 ]; do
112       set -- "$@" "$1" "pages/${moveto}/#attachments/${1##*/}"
113       cnt=$((cnt - 1)); shift 1
114     done
115
116     git -C "$_DATA" commit -qm \
117         "Attachment moved from # $page # to # $moveto # by @ $USER_NAME @" -- "$@"
118   else
119     mkdir -p -- "${_DATA}/pages${moveto}/#attachments"
120     ( cd "$_DATA" && mv -- "$@" "pages${moveto}/#attachments/"; )
121   fi
122   REDIRECT "${_BASE}${PATH_INFO}"
123
124 elif [ "$action" = rename ]; then
125   fail='' success=''
126   set --
127
128   for file in "${_DATA}/pages${page}#attachments"/*; do
129     rename="$(POST rename_"$(slopecode "${file##*/}" |sed 's;=;%3D;g')")"
130
131     if [ "$REV_ATTACHMENTS" = true -a \
132          -f "${file}" -a \
133          "$rename" -a \
134          "${rename%/*}" = "${rename}" -a \
135          ! -e "${_DATA}/pages${page}#attachments/${rename}" ] \
136        && git -C "$_DATA" mv -- "pages${page}#attachments/${file##*/}" "pages${page}#attachments/${rename}"; then
137       success="${success}$(HTML "${file##*/}/${rename}")${BR}"
138       set -- "$@" "pages${page}#attachments/${file##*/}" "pages${page}#attachments/${rename}"
139
140     elif [ "$REV_ATTACHMENTS" = true -a "${rename}" ]; then
141       fail="${fail}$(HTML "${file##*/}/${rename}")${BR}"
142
143     elif [ -f "${file}" -a \
144            "$rename" -a \
145            "${rename%/*}" = "${rename}" -a \
146            ! -e "${_DATA}/pages${page}#attachments/${rename}" ] \
147          && mv -- "${file}" "${_DATA}/pages${page}#attachments/${rename}"; then
148       success="${success}$(HTML "${file##*/}/${rename}")${BR}"
149
150     elif [ "${rename}" ]; then
151       fail="${fail}$(HTML "${file##*/}/${rename}")${BR}"
152
153     fi
154   done
155
156   if [ "$REV_ATTACHMENTS" = true -a $# -gt 2 ]; then
157     git -C "$_DATA" commit -qm \
158         "Attachment files renamed by @ $USER_NAME @" -- "$@"
159   elif [ "$REV_ATTACHMENTS" = true -a $# -eq 2 ]; then
160     git -C "$_DATA" commit -qm \
161         "Attachment file renamed by @ $USER_NAME @" -- "$@"
162   fi
163
164   if [ "$success" -a "$fail" ]; then
165     printf "%s\r\n" "Status: 500 Internal Server Error"
166     theme_page - "Attachment rename" <<-EOF
167         <h1 class="rename partial">Some files could not be renamed</h1>
168         <h2 class="rename success">Successfully renamed:</h2>
169         <ul class="rename success">
170         $(printf %s "$success" |while read html; do
171           printf '<li><span class=from>%s</span> -&gt; <span class=to>%s</span></li>' \
172                  "${html%%/*}" "${html##*/}"
173         done)
174         </ul>
175         <h2 class="rename fail">Errors:</h2>
176         <ul class="rename fail">
177         $(printf %s "$fail" |while read html; do
178           printf '<li><span class=from>%s</span> -&gt; <span class=to>%s</span></li>' \
179                  "${html%%/*}" "${html##*/}"
180         done)
181         </ul>
182         <a class="button rename fail" href="[attachment]">OK</a>
183         EOF
184     exit 0
185
186   elif [ "$fail" ]; then
187     printf "%s\r\n" "Status: 500 Internal Server Error"
188     theme_page - "Attachment rename" <<-EOF
189         <h1 class="rename fail">Files could not be renamed</h1>
190         <ul class="rename fail">
191         $(printf %s "$fail" |while read html; do
192           printf '<li><span class=from>%s</span> -&gt; <span class=to>%s</span></li>' \
193                  "${html%%/*}" "${html##*/}"
194         done)
195         </ul>
196         <a class="button rename fail" href="[attachment]">OK</a>
197         EOF
198     exit 0
199
200   elif [ "$success" ]; then
201     printf 'Refresh: %i\r\n' 4
202     theme_page - "Attachment rename" <<-EOF
203         <h1 class="rename success">Files were renamed</h1>
204         <ul class="rename success">
205         $(printf %s "$success" |while read html; do
206           printf '<li><span class=from>%s</span> -&gt; <span class=to>%s</span></li>' \
207                  "${html%%/*}" "${html##*/}"
208         done)
209         </ul>
210         <a class="button rename success" href="[attachment]">OK</a>
211         EOF
212     exit 0
213
214   else
215     REDIRECT "${_BASE}${PATH_INFO}"
216
217   fi
218 fi
219
220 return 1