]> git.plutz.net Git - shellwiki/blob - handlers/60_move_rename_delete.sh
Merge commit '6bc502434737d7f08379e79b94fc6fda424ef779'
[shellwiki] / handlers / 60_move_rename_delete.sh
1 #!/bin/sh
2
3 # Copyright 2022 - 2024 Paul Hänsch
4
5 # Permission to use, copy, modify, and/or distribute this software for any
6 # purpose with or without fee is hereby granted, provided that the above
7 # copyright notice and this permission notice appear in all copies.
8
9 # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12 # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17 l10n_immutablepage >/dev/null 2>&1 \
18 || l10n_immutablepage(){  #TRANSLATION
19   cat <<-EOF
20           <h1>Immutable Page</h1>
21           This is a core page of the wiki system. Its name and position cannot be changed.
22           You may however update this page and you can use ACLs to hide it from various listings.
23         EOF
24 }
25
26 case "${PATH_INFO}" in
27   */\[move\]|*/\[rename\]|*/\[delete\])
28     page="${PATH_INFO%\[*\]}"
29     if [ ! -d "$_DATA/pages/${page}" -a ! -d "$_EXEC/pages/${page}" ]; then
30       theme_error 404
31       return 0
32     elif ! acl_write "$page"; then
33       printf 'Refresh: %i, url=%s\r\n' 4 ./
34       theme_error 403
35       return 0
36     elif [ ! -d "$_DATA/pages/${page}" -a -d "$_EXEC/pages/${page}" ]; then
37       theme_page - <<-EOF
38         <article>
39           <p class=error>
40           $(l10n_immutablepage)
41           </p>
42         </article>
43         EOF
44       return 0
45     fi
46     ;;
47   *) return 1;;
48 esac
49
50 l10n_movepage >/dev/null 2>&1 \
51 || l10n_movepage(){  # TRANSLATION
52   cat <<-EOF
53           <h1>Move Page</h1>
54           <p class="pageid">$(HTML "${page}")</p>
55           <input list="locations" autocomplete="off" name="newlocation" value="$(HTML "$location")" placeholder="New Location">
56           <ul>
57             <li>A page with the same name must not already exist at the new location.</li>
58             <li>You must have permission to create new pages at this location.</li>
59             <li>All subpages will become available under the new path name.</li>
60             <li>Subpages will become unavailable under their current name.</li>
61           </ul>
62           <button type=submit name=action value=move>Move</button>
63           <button type=submit name=action value=cancel>Cancel</button>
64         EOF
65 }
66 l10n_renamepage >/dev/null 2>&1 \
67 || l10n_renamepage(){  # TRANSLATION
68   cat <<-EOF
69           <h1>Rename Page</h1>
70           <p class="pageid">$(HTML "${page}")</p>
71           <input autocomplete="off" name="newname" value="$(HTML "$name")" placeholder="New Name">
72           <ul>
73             <li>A page with the new name must not already exist.</li>
74             <li>You must have permission to create new pages at this location.</li>
75             <li>All subpages will become available under the new path name.</li>
76             <li>Subpages will become unavailable under their current name.</li>
77           </ul>
78           <button type=submit name=action value=rename>Rename</button>
79           <button type=submit name=action value=cancel>Cancel</button>
80         EOF
81 }
82 l10n_deletepage >/dev/null 2>&1 \
83 || l10n_deletepage(){  # TRANSLATION
84   cat <<-EOF
85           <h1>Delete Page</h1>
86           <p class="pageid">$(HTML "${page}")</p>
87           <p>This page and its attachments will be deleted</p>
88           <input type=checkbox name=delete_subpages value=true id=delsub><label for=delsub>Delete subpages</label>
89           <ul>
90         EOF
91   [ "$REV_PAGES" = true ] \
92   && printf '    <li>Past revisions of the page text (including the current one) will remain accessible and can be restored.</li>'
93   [ "$REV_PAGES" = true -a "$REV_ATTACHMENTS" = true ] \
94   && printf '    <li>Attachments can be restored as well.</li>' \
95   || printf '    <li>Attachments will be deleted completely, and cannot be restored.</li>'
96   cat <<-EOF
97             <li class="delsub">Subpages will not be affected and can still be accessed normally.</li>
98           </ul>
99           <button type=submit name=action value=delete>Delete</button>
100           <button type=submit name=action value=cancel>Cancel</button>
101         EOF
102 }
103
104 list_writable() {
105   local PATH_INFO page="${1%/}/"
106
107   if acl_write "$page"; then
108     PATH_INFO="$page"
109     page_glob "*" 0 \
110     | while read page; do
111       list_writable "${PATH_INFO}${page}"
112     done
113     printf %s\\n "$page" |debug
114   fi
115 }
116
117 if [ "$REQUEST_METHOD" = POST ]; then
118   action="$(POST action)"
119   newname="$(POST newname |grep -m1 -xE '[^#/]*')"
120   newlocation="$(POST newlocation |grep -m1 -xE '/[^#]*')"
121   delsub="$(POST delete_subpages |grep -m1 -xE 'true|false')"
122 else case "${PATH_INFO}" in
123   */\[move\])
124       location="${page%/}" location="${location%/*}/"
125       theme_page - "$(_ Move): ${PAGE_TITLE}"<<-EOF
126         <form method=POST id=movepage>
127           <input type=hidden name=session_id value="$SESSION_KEY">
128           <datalist id="locations">
129           $(page_glob / -1 |while read loc; do
130             [ "$loc" = "$page" ] && continue
131             acl_write "$loc" || continue
132             printf '\n    <option>%s</option>' "$(HTML "$loc")"
133           done)
134           </datalist>
135           $(l10n_movepage)
136         </form>
137         EOF
138       return 0
139     ;;
140   */\[rename\])
141       name="${page%/}" name="${name##*/}"
142       theme_page - "$(_ Rename): ${PAGE_TITLE}"<<-EOF
143         <form method=POST id=renamepage>
144           <input type=hidden name=session_id value="$SESSION_KEY">
145           $(l10n_renamepage)
146         </form>
147         EOF
148       return 0
149     ;;
150   */\[delete\])
151       theme_page - "$(_ Delete): ${PAGE_TITLE}"<<-EOF
152         <form method=POST id=deletepage>
153           <input type=hidden name=session_id value="$SESSION_KEY">
154           $(l10n_deletepage)
155         </form>
156         EOF
157       return 0
158     ;;
159   esac
160 fi
161
162 if [ "$action" = rename -a "$newname" ]; then
163   oldname="${PATH_INFO%\[*\]}"
164   newname="${oldname%/*/}$(PATH "${newname}/")"
165
166   if [ -d "$_DATA/pages/$newname" ]; then
167     printf 'Refresh: %i\r\n' 4
168     export ERROR_MSG="A location of that name already exists."
169     theme_error 400
170     return 0
171   elif ! acl_write "$oldname" || ! acl_write "$newname"; then
172     printf 'Refresh: %i\r\n' 4
173     theme_error 403
174     return 0
175   fi
176   if [ "$REV_PAGES" = true ]; then
177     git -C "$_DATA" mv "pages/$oldname" "pages/$newname"
178     git -C "$_DATA" commit -m 'Page # '"$oldname"' # renamed to # '"$newname"' # by user @ '"$USER_NAME"' @' \
179         -- "pages/$oldname" "pages/$newname"
180   else
181     mv -- "$_DATA/pages/$oldname" "$_DATA/pages/$newname"
182   fi
183   if [ "$SEARCH_INDEX" = true ]; then
184     find "$_DATA/pages/$newname" -name "#index.flag" -delete
185     ( "$_EXEC/searchindex.sh" index --location "$newname" & ) &
186   fi
187   REDIRECT "$_BASE${newname}"
188
189 elif [ "$action" = move -a "$newlocation" ]; then
190   oldname="${PATH_INFO%\[*\]}"
191   newlocation="$(PATH "$newlocation")"
192   newname="${oldname%/}"
193   newname="${newlocation%/}/${newname##*/}/"
194
195   if [ -d "$_DATA/pages/$newname" ]; then
196     printf 'Refresh: %i\r\n' 4
197     export ERROR_MSG="A page of that name already exists at the given location."
198     theme_error 400
199     return 0
200   elif [ ! -d "$_DATA/pages/$newlocation" ]; then
201     printf 'Refresh: %i\r\n' 4
202     export ERROR_MSG="The given location does not exist."
203     theme_error 400
204     return 0
205   elif ! acl_write "$oldname" || ! acl_write "$newname"; then
206     printf 'Refresh: %i\r\n' 4
207     theme_error 403
208     return 0
209   fi
210   if [ "$REV_PAGES" = true ]; then
211     git -C "$_DATA" mv "pages/${oldname}" "pages/${newname}"
212     git -C "$_DATA" commit -m 'Page # '"$oldname"' # moved to # '"$newname"' # by user @ '"$USER_NAME"' @' \
213         -- "pages/${oldname}" "pages/${newname}"
214   else
215     mv -- "$_DATA/pages/$oldname" "$_DATA/pages/$newname"
216   fi
217   if [ "$SEARCH_INDEX" = true ]; then
218     find "$_DATA/pages/$newname" -name "#index.flag" -delete
219     ( "$_EXEC/searchindex.sh" index --location "$newname" & ) &
220   fi
221   REDIRECT "$_BASE${newname}"
222
223 elif [ "$action" = delete ]; then
224   oldname="${PATH_INFO%\[*\]}"
225   if ! acl_write "$oldname"; then
226     printf 'Refresh: %i\r\n' 4
227     theme_error 403
228     return 0
229   fi
230
231   printf 'Status: 202 Accepted\r\n'
232   { [ "$delsub" = true ] \
233     && list_writable "$oldname" \
234     || printf %s\\n "$oldname"
235   } | while read oldname; do
236     if [ "$REV_PAGES" = true -a "$REV_ATTACHMENTS" = true ]; then
237       git -C "$_DATA" rm "pages/${oldname}/#page.md" >&2
238       git -C "$_DATA" rm -r "pages/${oldname}/#attachments/" >&2
239       git -C "$_DATA" commit -m 'Page # '"$oldname"' # deleted by user @ '"$USER_NAME"' @' \
240           -- "pages/${oldname}/#page.md" "pages/${oldname}/#attachments/" >&2
241       rm -r -- "$_DATA/pages/${oldname}"/\#*
242       rmdir -- "$_DATA/pages/${oldname}/" || true
243     elif [ "$REV_PAGES" = true ]; then
244       git -C "$_DATA" rm "pages/${oldname}/#page.md" >&2
245       git -C "$_DATA" commit -m 'Page # '"$oldname"' # deleted by user @ '"$USER_NAME"' @' \
246           -- "pages/${oldname}/#page.md" >&2
247       rm -r -- "$_DATA/pages/${oldname}"/\#*
248       rmdir -- "$_DATA/pages/${oldname}/" || true
249     else
250       rm -- "$_DATA/pages/${oldname}/#page.md"
251       rm -r -- "$_DATA/pages/${oldname}"/\#*
252       rmdir -- "$_DATA/pages/${oldname}/" || true
253     fi
254     printf '%s\n' "$oldname"
255   done | {
256     cat <<-EOF
257         <article id="deleteconfirm">
258           <h1>$(_ "Pages deleted:")</h1>
259           <ul>
260           $(while read page; do
261             printf '<li>%s</li>' "$(HTML $page)"
262           done)
263           </ul>
264           <a class="button" href="./">$(_ OK)</a>
265         </article>
266         EOF
267   } | theme_page -
268   return 0
269 elif [ "$action" = cancel ]; then
270   REDIRECT ./
271 elif [ "$action" ]; then
272   printf 'Refresh: %i\r\n' 4
273   export ERROR_MSG="Missing parameters."
274   theme_error 400
275   return 0
276 fi