X-Git-Url: http://git.plutz.net/?a=blobdiff_plain;f=handlers%2F20_attachment.sh;h=a1168978d769f5d57ce90829a5e1abed756c10fc;hb=1b8f9a660793917c33769e345500814f5b5cdd60;hp=0e9757e78f564a45a1a6097c99ec0b08861f38d6;hpb=b86e88d2d6acd3eda7d9858539818a290db67d41;p=shellwiki diff --git a/handlers/20_attachment.sh b/handlers/20_attachment.sh index 0e9757e..a116897 100755 --- a/handlers/20_attachment.sh +++ b/handlers/20_attachment.sh @@ -1,5 +1,9 @@ #!/bin/sh +. "$_EXEC/cgilite/file.sh" + +REV_ATTACHMENTS="${REV_ATTACHMENTS:-false}" + attachment_convert(){ local attpath="$1" local cachepath="${attpath%/#attachments/*}/#cache/${attpath#*/#attachments/}" @@ -59,92 +63,145 @@ attachment_convert(){ printf %s "$attpath" return 0 ;; + *) printf "$attpath";; esac } -if [ "${PATH_INFO%/\[attachment\]/}" != "${PATH_INFO}" ]; then - tsid="$(POST session_key)"; tsid="${tsid%% *}" - attachment_delete="$(POST delete)" +case ${PATH_INFO} in + */\[attachment\]/) + # no trailing slash + REDIRECT "${_BASE}${PATH_INFO%/}" + ;; + */*/) + # attached files never end on / + return 1 + ;; + */\[attachment\]) + # show attachment page + # receive uploads + tsid="$(POST session_key)"; tsid="${tsid%% *}" + action="$(POST action)" + attachment_delete="$(POST delete)" + page="${PATH_INFO%\[attachment\]}" + + if [ ! -d "$_DATA/pages${page}" -a ! -d "$_DATA/pages${page}" ]; then + # base page does not exist + return 1 + elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ] && acl_write "${page}"; then + . "$_EXEC/multipart.sh" + multipart_cache + + # Use positional parameters for filename collection + # The positional array is the only array available + # in plain posix shells, see the documentation for + # your shells "set" builtin for a hint to this + # obscure use mode + set -- - if [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ] && acl_write "${PATH_INFO%\[attachment\]/}"; then - . "$_EXEC/multipart.sh" - multipart_cache + # Validate session id from form to prevent CSRF + # Only validate if username is present, because no username means + # anonymous uploads are allowed via acl and cgilite/session.sh does not + # validate anonymous sessions from a multipart/formdata + if [ "$USER_NAME" -a "$(multipart session_id)" != "$SESSION_ID" ]; then + rm -- "$multipart_cachefile" + printf 'Refresh: %i\r\n' 4 + theme_error 403 + return 0 + fi - # Validate session id from form to prevent CSRF - # Only validate if username is present, because no username means - # anonymous uploads are allowed via acl and cgilite/session.sh does not - # validate anonymous sessions from a multipart/formdata - if [ "$USER_NAME" -a "$(multipart session_id)" != "$SESSION_ID" ]; then + mkdir -p "$_DATA/pages${page}#attachments/" + n=1; while filename=$(multipart_filename "file" "$n"); do + filename="$(printf %s "$filename" |tr /\\0 __)" + set -- "$@" "pages${page}#attachments/$filename" + multipart "file" "$n" >"$_DATA/pages${page}#attachments/$filename" + n=$((n + 1)) + done rm -- "$multipart_cachefile" + if [ "$REV_ATTACHMENTS" = true ]; then + git -C "$_DATA" add -- "$@" + git -C "$_DATA" commit -qm "Attachments to # $page # uploaded by @ $USER_NAME @" -- "$@" + fi + REDIRECT "${_BASE}${PATH_INFO}" + elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ]; then printf 'Refresh: %i\r\n' 4 theme_error 403 + head -c $((CONTENT_LENGTH)) >/dev/null + return 0 + elif [ "$action" = delete -a "$SESSION_ID" = "$tsid" ] && acl_write "${page}"; then + set -- + n="$(POST_COUNT select)"; while [ $n -gt 0 ]; do + delete="$(POST select $n |PATH)" + set -- "$@" "pages${page}#attachments/${delete##*/}" + n=$((n - 1)) + done + if [ "$REV_ATTACHMENTS" = true ]; then + git -C "$_DATA" rm -- "$@" + git -C "$_DATA" commit -qm \ + "Attachment to # $page # deleted by @ $USER_NAME @" -- "$@" + else + rm -- "$@" + fi + REDIRECT "${_BASE}${PATH_INFO}" + elif [ "$action" = delete ]; then + printf 'Refresh: %i\r\n' 4 + theme_error 403 + return 0 + # elif [ "$attachment_delete" -a "$SESSION_ID" = "$tsid" ]; then + # if [ "$REV_ATTACHMENTS" = true ]; then + # git -C "$_DATA" rm -- \ + # "$_DATA/pages${page}#attachments/$attachment_delete" + # git -C "$_DATA" commit -qm \ + # "Attachment to # $page # deleted by @ $USER_NAME @" -- \ + # "$_DATA/pages${page}#attachments/$attachment_delete" + # else + # rm -- "$_DATA/pages${page}#attachments/$attachment_delete" + # fi + # REDIRECT "${_BASE}${PATH_INFO}" + # elif [ "$attachment_delete" ]; then + # printf 'Refresh: %i\r\n' 4 + # theme_error 403 + # return 0 + elif ! acl_read "${page}"; then + theme_error 403 + return 0 + else + theme_attachments "${page}" return 0 fi + ;; - mkdir -p "$_DATA/pages/${PATH_INFO%/\[attachment\]/}/#attachments/" - n=1; while filename=$(multipart_filename "file" "$n"); do - filename="$(printf %s "$filename" |tr /\\0 __)" - multipart "file" "$n" >"$_DATA/pages/${PATH_INFO%/\[attachment\]/}/#attachments/$filename" - n=$((n + 1)) - done - rm -- "$multipart_cachefile" - REDIRECT "${_BASE}${PATH_INFO}" - elif [ "${CONTENT_TYPE%%;*}" = "multipart/form-data" ]; then - printf 'Refresh: %i\r\n' 4 - theme_error 403 - head -c $((CONTENT_LENGTH)) >/dev/null - return 0 - elif [ "$attachment_delete" -a "$SESSION_ID" = "$tsid" ]; then - rm -- "$_DATA/pages/${PATH_INFO%/\[attachment\]/}/#attachments/$attachment_delete" - REDIRECT "${_BASE}${PATH_INFO}" - elif [ "$attachment_delete" ]; then - printf 'Refresh: %i\r\n' 4 - theme_error 403 - return 0 - elif acl_read "${PATH_INFO%\[attachment\]/}"; then - theme_attachments "${PATH_INFO%\[attachment\]/}" - return 0 - else - theme_error 404 - return 0 - fi - -elif [ "${PATH_INFO%/\[attachment\]/*}" != "${PATH_INFO}" ]; then - attpath="${PATH_INFO%/\[attachment\]/*}/#attachments/${PATH_INFO##*/}" + */\[attachment\]/*) + attpath="${PATH_INFO%/\[attachment\]/*}/#attachments/${PATH_INFO##*/}" - if ! acl_read "${PATH_INFO%/\[attachment\]/*}"; then - theme_error 403 - return 0 - elif [ -f "$_DATA/pages/$attpath" ]; then - FILE "$_DATA/pages/$attpath" - return 0 - elif [ -f "$_EXEC/pages/$attpath" ]; then - FILE "$_EXEC/pages/$attpath" - return 0 - else - theme_error 404 - return 0 - fi -# exit 0; - -elif [ "${PATH_INFO%/}" = "${PATH_INFO}" ]; then - attpath="${PATH_INFO%/*}/#attachments/${PATH_INFO##*/}" + if [ ! -f "$_DATA/pages/$attpath" -a ! -f "$_EXEC/pages/$attpath" ]; then + return 1 + elif ! acl_read "${PATH_INFO%/\[attachment\]/*}"; then + theme_error 403 + return 0 + elif [ -f "$_DATA/pages/$attpath" ]; then + FILE "$_DATA/pages/$attpath" + return 0 + elif [ -f "$_EXEC/pages/$attpath" ]; then + FILE "$_EXEC/pages/$attpath" + return 0 + fi + ;; + */*) + attpath="${PATH_INFO%/*}/#attachments/${PATH_INFO##*/}" - if ! acl_read "${PATH_INFO%/*}/"; then - theme_error 403 - return 0 - elif [ -f "$_DATA/pages/$attpath" ]; then - FILE "$(attachment_convert "$_DATA/pages/$attpath")" - return 0 - elif [ -f "$_EXEC/pages/$attpath" ]; then - FILE "$(attachment_convert "$_EXEC/pages/$attpath")" - return 0 - elif [ -d "$_DATA/pages/${PATH_INFO}" -o -d "$_EXEC/pages/${PATH_INFO}" ]; then - REDIRECT "${_BASE}${PATH_INFO}/" - elif [ "${PATH_INFO%\[*\]}" = "${PATH_INFO}" ]; then - theme_error 404 - return 0 - fi -fi + if [ ! -f "$_DATA/pages/$attpath" -a ! -f "$_EXEC/pages/$attpath" ]; then + return 1 + elif ! acl_read "${PATH_INFO%/*}/"; then + theme_error 403 + return 0 + elif [ -f "$_DATA/pages/$attpath" ]; then + FILE "$(attachment_convert "$_DATA/pages/$attpath")" + return 0 + elif [ -f "$_EXEC/pages/$attpath" ]; then + FILE "$(attachment_convert "$_EXEC/pages/$attpath")" + return 0 + fi + ;; +esac return 1