simplefiles

A lightweight C CGI web application for managing files.
git clone https://scm.kuandu.systems/git-raw/simplefiles.git
Log | Files | Refs | README | LICENSE

upload.sh (31942B)


      1 #!/bin/sh
      2 
      3 set -eu
      4 
      5 . "$(dirname "$0")/testlib.sh"
      6 
      7 CGI=${1:-build/upload.cgi}
      8 
      9 upload_get() {
     10   env \
     11     STORAGE_ROOT="$TESTROOT/storage" \
     12     SIMPLEFILES_ROOT=./html \
     13     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
     14     REMOTE_USER=bob \
     15     REQUEST_METHOD=GET \
     16     "$CGI"
     17 }
     18 
     19 upload_put() {
     20   env \
     21     STORAGE_ROOT="$TESTROOT/storage" \
     22     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
     23     REMOTE_USER=bob \
     24     REQUEST_METHOD=PUT \
     25     "$CGI"
     26 }
     27 
     28 upload_post() {
     29   content_type=$1
     30   content_length=$2
     31 
     32   env \
     33     STORAGE_ROOT="$TESTROOT/storage" \
     34     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
     35     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
     36     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
     37     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
     38     REMOTE_USER=bob \
     39     REQUEST_METHOD=POST \
     40     CONTENT_TYPE="$content_type" \
     41     CONTENT_LENGTH="$content_length" \
     42     "$CGI"
     43 }
     44 
     45 upload_post_no_length() {
     46   content_type=$1
     47 
     48   env \
     49     STORAGE_ROOT="$TESTROOT/storage" \
     50     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
     51     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
     52     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
     53     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
     54     REMOTE_USER=bob \
     55     REQUEST_METHOD=POST \
     56     CONTENT_TYPE="$content_type" \
     57     "$CGI"
     58 }
     59 
     60 upload() {
     61   body=$(
     62     printf '%s\r\n' '--test'
     63     printf '%s\r\n' \
     64       'Content-Disposition: form-data; name="file"; filename="hello world.mp4"'
     65     printf '%s\r\n' 'Content-Type: video/mp4'
     66     printf '\r\n'
     67     printf '%s' 'dummy data'
     68     printf '\r\n--test--\r\n'
     69   )
     70 
     71   printf '%s' "$body" |
     72     env \
     73       STORAGE_ROOT="$TESTROOT/storage" \
     74       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
     75       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
     76       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
     77       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
     78       REMOTE_USER=bob \
     79       REQUEST_METHOD=POST \
     80       CONTENT_TYPE="multipart/form-data; boundary=test" \
     81       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
     82       "$CGI"
     83 }
     84 
     85 upload_boundary_in_file() {
     86   body=$(
     87     printf '%s\r\n' '--test'
     88     printf '%s\r\n' \
     89       'Content-Disposition: form-data; name="file"; filename="boundary.txt"'
     90     printf '%s\r\n' 'Content-Type: text/plain'
     91     printf '\r\n'
     92     printf '%s' 'before
     93 --test-not-a-boundary
     94 after'
     95     printf '\r\n--test--\r\n'
     96   )
     97 
     98   printf '%s' "$body" |
     99     env \
    100       STORAGE_ROOT="$TESTROOT/storage" \
    101       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    102       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    103       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    104       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    105       REMOTE_USER=bob \
    106       REQUEST_METHOD=POST \
    107       CONTENT_TYPE="multipart/form-data; boundary=test" \
    108       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    109       "$CGI"
    110 }
    111 
    112 upload_boundary_split() {
    113   tmp=$(mktemp)
    114 
    115   {
    116     printf '%s\r\n' '--test'
    117     printf '%s\r\n' \
    118       'Content-Disposition: form-data; name="file"; filename="split.txt"'
    119     printf '%s\r\n' 'Content-Type: text/plain'
    120     printf '\r\n'
    121 
    122     awk 'BEGIN {
    123       for (i = 0; i < 8192; i++)
    124         printf "A"
    125     }'
    126 
    127     printf '\r\n--test--\r\n'
    128   } > "$tmp"
    129 
    130   env \
    131     STORAGE_ROOT="$TESTROOT/storage" \
    132     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    133     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    134     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    135     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    136     REMOTE_USER=bob \
    137     REQUEST_METHOD=POST \
    138     CONTENT_TYPE="multipart/form-data; boundary=test" \
    139     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    140     "$CGI" < "$tmp"
    141 
    142   rm -f "$tmp"
    143 }
    144 
    145 upload_quota_ok() {
    146   tmp=$(mktemp)
    147 
    148   {
    149     printf '%s\r\n' '--test'
    150     printf '%s\r\n' \
    151       'Content-Disposition: form-data; name="file"; filename="quota_ok.txt"'
    152     printf '%s\r\n' 'Content-Type: application/octet-stream'
    153     printf '\r\n'
    154     awk 'BEGIN { for (i = 0; i < 100; i++) printf "A" }'
    155     printf '\r\n--test--\r\n'
    156   } > "$tmp"
    157 
    158   env \
    159     REPO_QUOTA_BYTES=10240 \
    160     STORAGE_ROOT="$TESTROOT/storage" \
    161     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    162     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    163     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    164     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    165     REMOTE_USER=bob \
    166     REQUEST_METHOD=POST \
    167     CONTENT_TYPE="multipart/form-data; boundary=test" \
    168     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    169     "$CGI" < "$tmp"
    170 
    171   rm -f "$tmp"
    172 }
    173 
    174 upload_quota_exceeds() {
    175   tmp=$(mktemp)
    176 
    177   {
    178     printf '%s\r\n' '--test'
    179     printf '%s\r\n' \
    180       'Content-Disposition: form-data; name="file"; filename="toobig.txt"'
    181     printf '%s\r\n' 'Content-Type: application/octet-stream'
    182     printf '\r\n'
    183     dd if=/dev/zero bs=1 count=2000 2> /dev/null
    184     printf '\r\n--test--\r\n'
    185   } > "$tmp"
    186 
    187   env \
    188     REPO_QUOTA_BYTES=10240 \
    189     MIN_FREE_BYTES=1024 \
    190     STORAGE_ROOT="$TESTROOT/storage" \
    191     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    192     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    193     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    194     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    195     REMOTE_USER=bob \
    196     REQUEST_METHOD=POST \
    197     CONTENT_TYPE="multipart/form-data; boundary=test" \
    198     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    199     "$CGI" < "$tmp"
    200 
    201   rm -f "$tmp"
    202 }
    203 
    204 upload_exact_quota() {
    205   quota=$1
    206   tmp=$(mktemp)
    207 
    208   {
    209     printf '%s\r\n' '--test'
    210     printf '%s\r\n' \
    211       'Content-Disposition: form-data; name="file"; filename="exact.txt"'
    212     printf '%s\r\n' 'Content-Type: application/octet-stream'
    213     printf '\r\n'
    214     dd if=/dev/zero bs=1 count=1024 2> /dev/null
    215     printf '\r\n--test--\r\n'
    216   } > "$tmp"
    217 
    218   env \
    219     REPO_QUOTA_BYTES="$quota" \
    220     STORAGE_ROOT="$TESTROOT/storage" \
    221     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    222     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    223     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    224     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    225     REMOTE_USER=bob \
    226     REQUEST_METHOD=POST \
    227     CONTENT_TYPE="multipart/form-data; boundary=test" \
    228     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    229     "$CGI" < "$tmp"
    230 
    231   rm -f "$tmp"
    232 }
    233 
    234 upload_filename() {
    235   filename=$1
    236 
    237   body=$(
    238     printf '%s\r\n' '--test'
    239     printf '%s\r\n' \
    240       "Content-Disposition: form-data; name=\"file\"; filename=\"$filename\""
    241     printf '%s\r\n' 'Content-Type: video/mp4'
    242     printf '\r\n'
    243     printf '%s' 'dummy data'
    244     printf '\r\n--test--\r\n'
    245   )
    246 
    247   printf '%s' "$body" |
    248     env \
    249       STORAGE_ROOT="$TESTROOT/storage" \
    250       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    251       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    252       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    253       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    254       REMOTE_USER=bob \
    255       REQUEST_METHOD=POST \
    256       CONTENT_TYPE="multipart/form-data; boundary=test" \
    257       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    258       "$CGI"
    259 }
    260 
    261 upload_truncated() {
    262   body=$(
    263     printf '%s\r\n' '--test'
    264     printf '%s\r\n' \
    265       'Content-Disposition: form-data; name="file"; filename="truncated.txt"'
    266     printf '%s\r\n' 'Content-Type: text/plain'
    267     printf '\r\n'
    268     printf '%s' 'partial data'
    269   )
    270 
    271   printf '%s' "$body" |
    272     env \
    273       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    274       STORAGE_ROOT="$TESTROOT/storage" \
    275       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    276       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    277       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    278       REMOTE_USER=bob \
    279       REQUEST_METHOD=POST \
    280       CONTENT_TYPE="multipart/form-data; boundary=test" \
    281       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    282       "$CGI"
    283 }
    284 
    285 upload_no_filename() {
    286   body=$(
    287     printf '%s\r\n' '--test'
    288     printf '%s\r\n' \
    289       'Content-Disposition: form-data; name="file"'
    290     printf '%s\r\n' 'Content-Type: text/plain'
    291     printf '\r\n'
    292     printf '%s' 'dummy data'
    293     printf '\r\n--test--\r\n'
    294   )
    295 
    296   printf '%s' "$body" |
    297     env \
    298       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    299       STORAGE_ROOT="$TESTROOT/storage" \
    300       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    301       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    302       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    303       REMOTE_USER=bob \
    304       REQUEST_METHOD=POST \
    305       CONTENT_TYPE="multipart/form-data; boundary=test" \
    306       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    307       "$CGI"
    308 }
    309 
    310 upload_malformed() {
    311   body=$(
    312     printf '%s\r\n' '--test'
    313     printf '%s\r\n' \
    314       'Content-Disposition: form-data; name="file"; filename="bad.txt"'
    315     printf '%s\r\n' 'Content-Type: text/plain'
    316     printf '%s\r\n' 'dummy data'
    317     printf '%s\r\n' '--test--'
    318   )
    319 
    320   printf '%s' "$body" |
    321     env \
    322       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    323       STORAGE_ROOT="$TESTROOT/storage" \
    324       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    325       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    326       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    327       REMOTE_USER=bob \
    328       REQUEST_METHOD=POST \
    329       CONTENT_TYPE="multipart/form-data; boundary=test" \
    330       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    331       "$CGI"
    332 }
    333 
    334 upload_failed_after_data() {
    335   tmp=$(mktemp)
    336 
    337   {
    338     printf '%s\r\n' '--test'
    339     printf '%s\r\n' \
    340       'Content-Disposition: form-data; name="file"; filename="failed.txt"'
    341     printf '%s\r\n' 'Content-Type: text/plain'
    342     printf '\r\n'
    343 
    344     awk 'BEGIN {
    345       for (i = 0; i < 8192; i++)
    346         printf "A"
    347     }'
    348   } > "$tmp"
    349 
    350   env \
    351     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    352     STORAGE_ROOT="$TESTROOT/storage" \
    353     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    354     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    355     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    356     REMOTE_USER=bob \
    357     REQUEST_METHOD=POST \
    358     CONTENT_TYPE="multipart/form-data; boundary=test" \
    359     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    360     "$CGI" < "$tmp"
    361 
    362   rm -f "$tmp"
    363 }
    364 
    365 upload_short_body() {
    366   body='short body'
    367 
    368   printf '%s' "$body" |
    369     env \
    370       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    371       STORAGE_ROOT="$TESTROOT/storage" \
    372       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    373       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    374       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    375       REMOTE_USER=bob \
    376       REQUEST_METHOD=POST \
    377       CONTENT_TYPE="multipart/form-data; boundary=test" \
    378       CONTENT_LENGTH=999 \
    379       "$CGI"
    380 }
    381 
    382 upload_min_free_rejected() {
    383   body=$(
    384     printf '%s\r\n' '--test'
    385     printf '%s\r\n' \
    386       'Content-Disposition: form-data; name="file"; filename="minfree.txt"'
    387     printf '%s\r\n' 'Content-Type: text/plain'
    388     printf '\r\n'
    389     printf '%s' 'dummy data'
    390     printf '\r\n--test--\r\n'
    391   )
    392 
    393   printf '%s' "$body" |
    394     env \
    395       STORAGE_ROOT="$TESTROOT/storage" \
    396       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    397       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    398       MIN_FREE_BYTES=9223372036854775807 \
    399       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    400       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    401       REMOTE_USER=bob \
    402       REQUEST_METHOD=POST \
    403       CONTENT_TYPE="multipart/form-data; boundary=test" \
    404       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    405       "$CGI"
    406 }
    407 
    408 upload_min_free_checked_before_spool() {
    409   body=$(
    410     printf '%s\r\n' '--test'
    411     printf '%s\r\n' \
    412       'Content-Disposition: form-data; name="file"; filename="minfree.txt"'
    413     printf '%s\r\n' 'Content-Type: text/plain'
    414     printf '\r\n'
    415     printf '%s' 'dummy data'
    416     printf '\r\n--test--\r\n'
    417   )
    418 
    419   bad_tmp="$TESTROOT/not-a-directory"
    420   printf '%s' > "$bad_tmp"
    421 
    422   printf '%s' "$body" |
    423     env \
    424       STORAGE_ROOT="$TESTROOT/storage" \
    425       UPLOAD_TMP_DIR="$bad_tmp" \
    426       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    427       MIN_FREE_BYTES=9223372036854775807 \
    428       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    429       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    430       REMOTE_USER=bob \
    431       REQUEST_METHOD=POST \
    432       CONTENT_TYPE="multipart/form-data; boundary=test" \
    433       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    434       "$CGI"
    435 }
    436 
    437 upload_min_free_allows() {
    438   body=$(
    439     printf '%s\r\n' '--test'
    440     printf '%s\r\n' \
    441       'Content-Disposition: form-data; name="file"; filename="minfree-ok.txt"'
    442     printf '%s\r\n' 'Content-Type: text/plain'
    443     printf '\r\n'
    444     printf '%s' 'dummy data'
    445     printf '\r\n--test--\r\n'
    446   )
    447 
    448   printf '%s' "$body" |
    449     env \
    450       STORAGE_ROOT="$TESTROOT/storage" \
    451       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    452       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    453       MIN_FREE_BYTES=1 \
    454       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    455       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    456       REMOTE_USER=bob \
    457       REQUEST_METHOD=POST \
    458       CONTENT_TYPE="multipart/form-data; boundary=test" \
    459       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    460       "$CGI"
    461 }
    462 
    463 upload_post_origin() {
    464   origin=$1
    465 
    466   body=$(
    467     printf '%s\r\n' '--test'
    468     printf '%s\r\n' \
    469       'Content-Disposition: form-data; name="file"; filename="csrf.txt"'
    470     printf '%s\r\n' 'Content-Type: text/plain'
    471     printf '\r\n'
    472     printf '%s' 'csrf test'
    473     printf '\r\n--test--\r\n'
    474   )
    475 
    476   printf '%s' "$body" |
    477     env \
    478       STORAGE_ROOT="$TESTROOT/storage" \
    479       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    480       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    481       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    482       HTTP_ORIGIN="$origin" \
    483       REMOTE_USER=bob \
    484       REQUEST_METHOD=POST \
    485       CONTENT_TYPE="multipart/form-data; boundary=test" \
    486       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    487       "$CGI"
    488 }
    489 
    490 upload_post_no_origin() {
    491   body=$(
    492     printf '%s\r\n' '--test'
    493     printf '%s\r\n' \
    494       'Content-Disposition: form-data; name="file"; filename="csrf.txt"'
    495     printf '%s\r\n' 'Content-Type: text/plain'
    496     printf '\r\n'
    497     printf '%s' 'csrf test'
    498     printf '\r\n--test--\r\n'
    499   )
    500 
    501   printf '%s' "$body" |
    502     env \
    503       STORAGE_ROOT="$TESTROOT/storage" \
    504       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    505       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    506       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    507       REQUEST_METHOD=POST \
    508       REMOTE_USER=bob \
    509       CONTENT_TYPE="multipart/form-data; boundary=test" \
    510       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    511       "$CGI"
    512 }
    513 
    514 upload_binary() {
    515   tmp=$(mktemp)
    516 
    517   {
    518     printf '%s\r\n' '--test'
    519     printf '%s\r\n' \
    520       'Content-Disposition: form-data; name="file"; filename="binary.bin"'
    521     printf '%s\r\n' 'Content-Type: application/octet-stream'
    522     printf '\r\n'
    523     printf '\000\001\002\003\377'
    524     printf '\r\n--test--\r\n'
    525   } > "$tmp"
    526 
    527   env \
    528     STORAGE_ROOT="$TESTROOT/storage" \
    529     UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    530     REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    531     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    532     HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    533     REMOTE_USER=bob \
    534     REQUEST_METHOD=POST \
    535     CONTENT_TYPE="multipart/form-data; boundary=test" \
    536     CONTENT_LENGTH="$(wc -c < "$tmp" | tr -d ' ')" \
    537     "$CGI" < "$tmp"
    538 
    539   rm -f "$tmp"
    540 }
    541 
    542 upload_post_user() {
    543   user=$1
    544 
    545   body=$(
    546     printf '%s\r\n' '--test'
    547     printf '%s\r\n' \
    548       'Content-Disposition: form-data; name="file"; filename="upload.txt"'
    549     printf '%s\r\n' 'Content-Type: text/plain'
    550     printf '\r\n'
    551     printf '%s' 'uploaded content'
    552     printf '\r\n--test--\r\n'
    553   )
    554 
    555   printf '%s' "$body" |
    556     env \
    557       SCRIPT_NAME=/default/upload.cgi \
    558       STORAGE_ROOT="$TESTROOT/storage" \
    559       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    560       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    561       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    562       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    563       REMOTE_USER="$user" \
    564       REQUEST_METHOD=POST \
    565       CONTENT_TYPE="multipart/form-data; boundary=test" \
    566       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    567       "$CGI"
    568 }
    569 
    570 upload_post_no_user() {
    571   body=$(
    572     printf '%s\r\n' '--test'
    573     printf '%s\r\n' \
    574       'Content-Disposition: form-data; name="file"; filename="upload.txt"'
    575     printf '%s\r\n' 'Content-Type: text/plain'
    576     printf '\r\n'
    577     printf '%s' 'uploaded content'
    578     printf '\r\n--test--\r\n'
    579   )
    580 
    581   (
    582     unset REMOTE_USER
    583 
    584     printf '%s' "$body" |
    585       STORAGE_ROOT="$TESTROOT/storage" \
    586       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    587       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    588       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    589       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    590       SCRIPT_NAME=/default/upload.cgi \
    591       REQUEST_METHOD=POST \
    592       CONTENT_TYPE="multipart/form-data; boundary=test" \
    593       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    594       "$CGI"
    595   )
    596 }
    597 
    598 upload_filename_in_body() {
    599   body=$(
    600     printf '%s\r\n' '--test'
    601     printf '%s\r\n' \
    602       'Content-Disposition: form-data; name="file"; filename="safe.txt"'
    603     printf '%s\r\n' 'Content-Type: text/plain'
    604     printf '\r\n'
    605     printf '%s' 'filename="evil.txt"'
    606     printf '\r\n--test--\r\n'
    607   )
    608 
    609   printf '%s' "$body" |
    610     env \
    611       STORAGE_ROOT="$TESTROOT/storage" \
    612       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    613       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    614       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    615       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    616       REMOTE_USER=bob \
    617       REQUEST_METHOD=POST \
    618       CONTENT_TYPE="multipart/form-data; boundary=test" \
    619       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    620       "$CGI"
    621 }
    622 
    623 upload_multiple_files() {
    624   body=$(
    625     printf '%s\r\n' '--test'
    626     printf '%s\r\n' \
    627       'Content-Disposition: form-data; name="file"; filename="one.txt"'
    628     printf '%s\r\n' 'Content-Type: text/plain'
    629     printf '\r\n'
    630     printf '%s\r\n' 'first file'
    631     printf '%s\r\n' '--test'
    632     printf '%s\r\n' \
    633       'Content-Disposition: form-data; name="file"; filename="two.txt"'
    634     printf '%s\r\n' 'Content-Type: text/plain'
    635     printf '\r\n'
    636     printf '%s\r\n' 'second file'
    637     printf '%s\r\n' '--test--'
    638   )
    639 
    640   printf '%s' "$body" |
    641     env \
    642       STORAGE_ROOT="$TESTROOT/storage" \
    643       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    644       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    645       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    646       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    647       REMOTE_USER=bob \
    648       REQUEST_METHOD=POST \
    649       CONTENT_TYPE="multipart/form-data; boundary=test" \
    650       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    651       "$CGI"
    652 }
    653 
    654 upload_cleanup_failure() {
    655   body=$(
    656     printf '%s\r\n' '--test'
    657     printf '%s\r\n' \
    658       'Content-Disposition: form-data; name="file"; filename="cleanup-failure.txt"'
    659     printf '%s\r\n' 'Content-Type: text/plain'
    660     printf '\r\n'
    661     printf '%s' 'published despite cleanup failure'
    662     printf '\r\n--test--\r\n'
    663   )
    664 
    665   printf '%s' "$body" |
    666     env \
    667       TEST_FAIL_TEMP_UNLINK=1 \
    668       STORAGE_ROOT="$TESTROOT/storage" \
    669       UPLOAD_TMP_DIR="$TEST_UPLOAD_DIR" \
    670       REPOSITORY_LOCK_DIR="$TEST_LOCK_DIR" \
    671       SIMPLEFILES_CONFIG="$TEST_CONFIG" \
    672       HTTP_ORIGIN="$TEST_CSRF_ORIGIN" \
    673       REMOTE_USER=bob \
    674       REQUEST_METHOD=POST \
    675       CONTENT_TYPE="multipart/form-data; boundary=test" \
    676       CONTENT_LENGTH="$(printf '%s' "$body" | wc -c | tr -d ' ')" \
    677       "$CGI"
    678 }
    679 
    680 ####################################################
    681 
    682 #
    683 # Request validation
    684 #
    685 
    686 reset_testroot
    687 
    688 write_default_repo_config "ADMIN_USER=bob"
    689 
    690 check_status \
    691   "GET upload page" \
    692   "200 OK" \
    693   upload_get
    694 
    695 check_status \
    696   "reject invalid method" \
    697   "405 Method Not Allowed" \
    698   upload_put
    699 
    700 check_body \
    701   "invalid method message" \
    702   "GET or POST required" \
    703   upload_put
    704 
    705 check_status \
    706   "reject missing content type" \
    707   "400 Bad Request" \
    708   upload_post \
    709   "" \
    710   10
    711 
    712 check_status \
    713   "reject invalid content type" \
    714   "400 Bad Request" \
    715   upload_post \
    716   "text/plain; boundary=test" \
    717   10
    718 
    719 check_status \
    720   "reject missing boundary" \
    721   "400 Bad Request" \
    722   upload_post \
    723   "multipart/form-data" \
    724   10
    725 
    726 check_status \
    727   "reject invalid length" \
    728   "400 Bad Request" \
    729   upload_post \
    730   "multipart/form-data; boundary=test" \
    731   abc
    732 
    733 check_status \
    734   "reject zero length" \
    735   "413 Payload Too Large" \
    736   upload_post \
    737   "multipart/form-data; boundary=test" \
    738   0
    739 
    740 check_status \
    741   "reject oversized upload" \
    742   "413 Payload Too Large" \
    743   upload_post \
    744   "multipart/form-data; boundary=test" \
    745   999999999
    746 
    747 check_status \
    748   "reject missing content length" \
    749   "411 Length Required" \
    750   upload_post_no_length \
    751   "multipart/form-data; boundary=test"
    752 
    753 check_status \
    754   "reject empty boundary" \
    755   "400 Bad Request" \
    756   upload_post \
    757   "multipart/form-data; boundary=" \
    758   10
    759 
    760 long_boundary=$(printf '%0129d' 0 | tr '0' 'a')
    761 
    762 check_status \
    763   "reject oversized boundary" \
    764   "400 Bad Request" \
    765   upload_post \
    766   "multipart/form-data; boundary=$long_boundary" \
    767   10
    768 
    769 ####################################################
    770 
    771 #
    772 # Multipart validation
    773 #
    774 
    775 check_status \
    776   "reject missing filename" \
    777   "400 Bad Request" \
    778   upload_no_filename
    779 
    780 check_status \
    781   "reject malformed multipart body" \
    782   "400 Bad Request" \
    783   upload_malformed
    784 
    785 check_status \
    786   "reject short request body" \
    787   "400 Bad Request" \
    788   upload_short_body
    789 
    790 check_redirect \
    791   "boundary-like string inside file" \
    792   "303 See Other" \
    793   "./" \
    794   upload_boundary_in_file
    795 
    796 check_file \
    797   "boundary-like string preserved" \
    798   "$TESTROOT/storage/default/boundary.txt" \
    799   "before
    800 --test-not-a-boundary
    801 after"
    802 
    803 check_redirect \
    804   "multipart boundary across reads" \
    805   "303 See Other" \
    806   "./" \
    807   upload_boundary_split
    808 
    809 check_file \
    810   "multipart data preserved across reads" \
    811   "$TESTROOT/storage/default/split.txt" \
    812   "$(awk 'BEGIN {
    813     for (i = 0; i < 8192; i++)
    814       printf "A"
    815   }')"
    816 
    817 check_redirect \
    818   "filename is extracted from headers only" \
    819   "303 See Other" \
    820   "./" \
    821   upload_filename_in_body
    822 
    823 check_file \
    824   "filename from header is preserved" \
    825   "$TESTROOT/storage/default/safe.txt" \
    826   'filename="evil.txt"'
    827 
    828 check_file_missing \
    829   "filename from body is not used" \
    830   "$TESTROOT/storage/default/evil.txt"
    831 
    832 ####################################################
    833 
    834 #
    835 # Multipart cardinatlity
    836 #
    837 
    838 reset_testroot
    839 
    840 write_default_repo_config "ADMIN_USER=bob"
    841 
    842 check_status \
    843   "reject multiple file upload" \
    844   "400 Bad Request" \
    845   upload_multiple_files
    846 
    847 check_file_missing \
    848   "multiple upload creates no first file" \
    849   "$TESTROOT/storage/default/one.txt"
    850 
    851 check_file_missing \
    852   "multiple upload creates no second file" \
    853   "$TESTROOT/storage/default/two.txt"
    854 
    855 ####################################################
    856 
    857 #
    858 # Standalone uploads
    859 #
    860 
    861 reset_testroot
    862 write_default_repo_config "ADMIN_USER=bob"
    863 
    864 check_redirect \
    865   "extract filename" \
    866   "303 See Other" \
    867   "./" \
    868   upload
    869 
    870 check_file \
    871   "file created" \
    872   "$TESTROOT/storage/default/hello world.mp4" \
    873   "dummy data"
    874 
    875 check_redirect \
    876   "duplicate upload redirects" \
    877   "303 See Other" \
    878   "./" \
    879   upload
    880 
    881 check_file \
    882   "duplicate file created" \
    883   "$TESTROOT/storage/default/hello world.1.mp4" \
    884   "dummy data"
    885 
    886 ####################################################
    887 
    888 #
    889 # Quota tests
    890 #
    891 
    892 reset_testroot
    893 write_default_repo_config "ADMIN_USER=bob"
    894 
    895 check_redirect \
    896   "upload within quota" \
    897   "303 See Other" \
    898   "./" \
    899   upload_quota_ok
    900 
    901 check_file \
    902   "quota ok file created" \
    903   "$TESTROOT/storage/default/quota_ok.txt" \
    904   "$(awk 'BEGIN { for (i = 0; i < 100; i++) printf "A" }')"
    905 
    906 reset_testroot
    907 write_default_repo_config "ADMIN_USER=bob"
    908 
    909 dd \
    910   if=/dev/zero \
    911   of="$TESTROOT/storage/default/filler.bin" \
    912   bs=1 \
    913   count=9000 \
    914   2> /dev/null
    915 
    916 check_status \
    917   "upload exceeds repo quota" \
    918   "507 Insufficient Storage" \
    919   upload_quota_exceeds
    920 
    921 ####################################################
    922 
    923 #
    924 # Upload at exact quota boundary
    925 #
    926 
    927 reset_testroot
    928 
    929 write_default_repo_config "ADMIN_USER=bob"
    930 
    931 dd \
    932   if=/dev/zero \
    933   of="$TESTROOT/storage/default/filler.bin" \
    934   bs=1 \
    935   count=9216 \
    936   2> /dev/null
    937 
    938 config_size=$(wc -c < "$TESTROOT/storage/default/.config" | tr -d ' ')
    939 exact_quota=$((9216 + 1024 + config_size))
    940 
    941 check_redirect \
    942   "upload at exact quota limit" \
    943   "303 See Other" \
    944   "./" \
    945   upload_exact_quota \
    946   "$exact_quota"
    947 
    948 ####################################################
    949 
    950 #
    951 # Default quota
    952 #
    953 
    954 reset_testroot
    955 write_default_repo_config "ADMIN_USER=bob"
    956 
    957 check_redirect \
    958   "default quota allows upload" \
    959   "303 See Other" \
    960   "./" \
    961   upload
    962 
    963 ####################################################
    964 
    965 #
    966 # Repository QUOTA
    967 #
    968 
    969 reset_testroot
    970 
    971 write_default_repo_config 'ADMIN_USER=bob
    972 QUOTA=1'
    973 
    974 check_status \
    975   "config quota rejects upload" \
    976   "507 Insufficient Storage" \
    977   upload
    978 
    979 reset_testroot
    980 
    981 write_default_repo_config 'ADMIN_USER=bob
    982 QUOTA=1024'
    983 
    984 check_redirect \
    985   "config quota allows upload" \
    986   "303 See Other" \
    987   "./" \
    988   upload
    989 
    990 ####################################################
    991 
    992 #
    993 # Repository MAX_UPLOAD
    994 #
    995 
    996 reset_testroot
    997 
    998 write_default_repo_config 'ADMIN_USER=bob
    999 MAX_UPLOAD=1'
   1000 
   1001 check_status \
   1002   "config max upload rejects upload" \
   1003   "413 Payload Too Large" \
   1004   upload
   1005 
   1006 reset_testroot
   1007 
   1008 write_default_repo_config 'ADMIN_USER=bob
   1009 MAX_UPLOAD=1024'
   1010 
   1011 check_redirect \
   1012   "config max upload allows upload" \
   1013   "303 See Other" \
   1014   "./" \
   1015   upload
   1016 
   1017 ####################################################
   1018 
   1019 #
   1020 # Repository MAX_UPLOAD + QUOTA
   1021 #
   1022 
   1023 reset_testroot
   1024 
   1025 write_default_repo_config 'ADMIN_USER=bob
   1026 MAX_UPLOAD=1024
   1027 QUOTA=1024'
   1028 
   1029 check_redirect \
   1030   "config max upload+quota" \
   1031   "303 See Other" \
   1032   "./" \
   1033   upload
   1034 
   1035 reset_testroot
   1036 
   1037 write_default_repo_config 'ADMIN_USER=bob
   1038 MAX_UPLOAD=1024
   1039 QUOTA=1'
   1040 
   1041 check_status \
   1042   "config max upload+quota rejects upload" \
   1043   "507 Insufficient Storage" \
   1044   upload
   1045 
   1046 ####################################################
   1047 
   1048 #
   1049 # Invalid filenames
   1050 #
   1051 
   1052 reset_testroot
   1053 write_default_repo_config "ADMIN_USER=bob"
   1054 
   1055 check_status \
   1056   "reject .config upload" \
   1057   "400 Bad Request" \
   1058   upload_filename \
   1059   ".config"
   1060 
   1061 check_status \
   1062   "reject path traversal filename" \
   1063   "400 Bad Request" \
   1064   upload_filename \
   1065   "../passwd"
   1066 
   1067 check_status \
   1068   "reject slash filename" \
   1069   "400 Bad Request" \
   1070   upload_filename \
   1071   "subdir/file.txt"
   1072 
   1073 check_status \
   1074   "reject empty filename" \
   1075   "400 Bad Request" \
   1076   upload_filename \
   1077   ""
   1078 
   1079 check_status \
   1080   "reject dot filename" \
   1081   "400 Bad Request" \
   1082   upload_filename \
   1083   "."
   1084 
   1085 check_status \
   1086   "reject dot-dot filename" \
   1087   "400 Bad Request" \
   1088   upload_filename \
   1089   ".."
   1090 
   1091 long_filename=$(awk 'BEGIN { for (i = 0; i < 300; i++) printf "a" }')
   1092 
   1093 check_status \
   1094   "reject oversized filename" \
   1095   "400 Bad Request" \
   1096   upload_filename \
   1097   "$long_filename"
   1098 
   1099 ####################################################
   1100 
   1101 #
   1102 # Temporary upload cleanup
   1103 #
   1104 
   1105 reset_testroot
   1106 write_default_repo_config "ADMIN_USER=bob"
   1107 
   1108 check_status \
   1109   "reject missing closing boundary" \
   1110   "400 Bad Request" \
   1111   upload_truncated
   1112 
   1113 check_no_temp_uploads \
   1114   "no temporary upload remains" \
   1115   "$TEST_UPLOAD_DIR"
   1116 
   1117 ####################################################
   1118 
   1119 #
   1120 # Failed upload cleanup
   1121 #
   1122 
   1123 reset_testroot
   1124 write_default_repo_config "ADMIN_USER=bob"
   1125 
   1126 check_status \
   1127   "reject failed upload" \
   1128   "400 Bad Request" \
   1129   upload_failed_after_data
   1130 
   1131 check_file_missing \
   1132   "failed upload leaves no destination file" \
   1133   "$TESTROOT/storage/default/failed.txt"
   1134 
   1135 check_no_temp_uploads \
   1136   "failed upload leaves no temporary file" \
   1137   "$TEST_UPLOAD_DIR"
   1138 
   1139 ####################################################
   1140 
   1141 #
   1142 # Minimum free space
   1143 #
   1144 
   1145 reset_testroot
   1146 write_default_repo_config "ADMIN_USER=bob"
   1147 
   1148 check_status \
   1149   "reject upload when minimum free space is not available" \
   1150   "507 Insufficient Storage" \
   1151   upload_min_free_rejected
   1152 
   1153 check_status \
   1154   "minimum-free check happens before spool creation" \
   1155   "507 Insufficient Storage" \
   1156   upload_min_free_checked_before_spool
   1157 
   1158 reset_testroot
   1159 write_default_repo_config "ADMIN_USER=bob"
   1160 
   1161 check_redirect \
   1162   "upload with sufficient minimum free space" \
   1163   "303 See Other" \
   1164   "./" \
   1165   upload_min_free_allows
   1166 
   1167 check_file \
   1168   "minimum-free upload created file" \
   1169   "$TESTROOT/storage/default/minfree-ok.txt" \
   1170   "dummy data"
   1171 
   1172 ####################################################
   1173 
   1174 #
   1175 # CSRF Origin protection
   1176 #
   1177 
   1178 reset_testroot
   1179 write_default_repo_config "ADMIN_USER=bob"
   1180 
   1181 check_status \
   1182   "upload accepts configured Origin" \
   1183   "303 See Other" \
   1184   upload_post_origin \
   1185   "$TEST_CSRF_ORIGIN"
   1186 
   1187 check_file \
   1188   "configured Origin upload creates file" \
   1189   "$TESTROOT/storage/default/csrf.txt" \
   1190   "csrf test"
   1191 
   1192 reset_testroot
   1193 write_default_repo_config "ADMIN_USER=bob"
   1194 
   1195 check_status \
   1196   "upload rejects missing Origin" \
   1197   "403 Forbidden" \
   1198   upload_post_no_origin
   1199 
   1200 check_file_missing \
   1201   "missing Origin creates no file" \
   1202   "$TESTROOT/storage/default/csrf.txt"
   1203 
   1204 reset_testroot
   1205 write_default_repo_config "ADMIN_USER=bob"
   1206 
   1207 check_status \
   1208   "upload rejects wrong Origin" \
   1209   "403 Forbidden" \
   1210   upload_post_origin \
   1211   "https://evil.example"
   1212 
   1213 check_file_missing \
   1214   "wrong Origin creates no file" \
   1215   "$TESTROOT/storage/default/csrf.txt"
   1216 
   1217 reset_testroot
   1218 write_default_repo_config "ADMIN_USER=bob"
   1219 
   1220 check_status \
   1221   "upload rejects Origin with configured origin as prefix" \
   1222   "403 Forbidden" \
   1223   upload_post_origin \
   1224   "https://localhost.evil.example"
   1225 
   1226 reset_testroot
   1227 write_default_repo_config "ADMIN_USER=bob"
   1228 
   1229 check_status \
   1230   "upload rejects wrong Origin scheme" \
   1231   "403 Forbidden" \
   1232   upload_post_origin \
   1233   "https://localhost:8000"
   1234 
   1235 ####################################################
   1236 
   1237 #
   1238 # Binary upload
   1239 #
   1240 
   1241 reset_testroot
   1242 write_default_repo_config "ADMIN_USER=bob"
   1243 
   1244 check_redirect \
   1245   "binary upload succeeds" \
   1246   "303 See Other" \
   1247   "./" \
   1248   upload_binary
   1249 
   1250 check_file_bytes \
   1251   "binary file preserved" \
   1252   "$TESTROOT/storage/default/binary.bin" \
   1253   '\000\001\002\003\377'
   1254 
   1255 ####################################################
   1256 
   1257 #
   1258 # Read-only repository
   1259 #
   1260 
   1261 reset_testroot
   1262 write_default_repo_config 'ADMIN_USER=bob
   1263 READ_ONLY=1'
   1264 
   1265 check_body \
   1266   "readonly GET upload rejected" \
   1267   "read-only" \
   1268   upload_get
   1269 
   1270 check_file_missing \
   1271   "readonly GET does not create file" \
   1272   "$TESTROOT/storage/default/readonly.txt"
   1273 
   1274 check_status \
   1275   "readonly POST upload rejected" \
   1276   "403 Forbidden" \
   1277   upload
   1278 
   1279 ####################################################
   1280 
   1281 #
   1282 # Authentication
   1283 #
   1284 
   1285 #
   1286 # ADMIN_USER configured: admin can upload.
   1287 #
   1288 
   1289 reset_testroot
   1290 
   1291 write_default_repo_config "ADMIN_USER=bob"
   1292 
   1293 check_status \
   1294   "admin user allowed to upload" \
   1295   "303 See Other" \
   1296   upload_post_user \
   1297   "bob"
   1298 
   1299 check_file \
   1300   "admin upload succeeds" \
   1301   "$TESTROOT/storage/default/upload.txt" \
   1302   "uploaded content"
   1303 
   1304 #
   1305 # ADMIN_USER configured: non-admin is rejected.
   1306 #
   1307 
   1308 reset_testroot
   1309 
   1310 write_default_repo_config "ADMIN_USER=bob"
   1311 
   1312 check_status \
   1313   "non-admin user rejected from upload" \
   1314   "403 Forbidden" \
   1315   upload_post_user \
   1316   "alice"
   1317 
   1318 check_file_missing \
   1319   "non-admin upload not created" \
   1320   "$TESTROOT/storage/default/upload.txt"
   1321 
   1322 #
   1323 # ADMIN_USER configured: anonymous is rejected.
   1324 #
   1325 
   1326 reset_testroot
   1327 
   1328 write_default_repo_config "ADMIN_USER=bob"
   1329 
   1330 check_status \
   1331   "anonymous upload rejected" \
   1332   "403 Forbidden" \
   1333   upload_post_no_user
   1334 
   1335 check_file_missing \
   1336   "anonymous upload not created" \
   1337   "$TESTROOT/storage/default/upload.txt"
   1338 
   1339 #
   1340 # No ADMIN_USER: anonymous is rejected.
   1341 #
   1342 
   1343 reset_testroot
   1344 
   1345 write_default_repo_config ""
   1346 
   1347 check_status \
   1348   "anonymous upload rejected without ADMIN_USER" \
   1349   "403 Forbidden" \
   1350   upload_post_no_user
   1351 
   1352 check_file_missing \
   1353   "anonymous upload without ADMIN_USER not created" \
   1354   "$TESTROOT/storage/default/upload.txt"
   1355 
   1356 #
   1357 # No ADMIN_USER: authenticated user is rejected.
   1358 #
   1359 
   1360 reset_testroot
   1361 
   1362 write_default_repo_config ""
   1363 
   1364 check_status \
   1365   "authenticated upload rejected without ADMIN_USER" \
   1366   "403 Forbidden" \
   1367   upload_post_user \
   1368   "alice"
   1369 
   1370 check_file_missing \
   1371   "authenticated upload without ADMIN_USER not created" \
   1372   "$TESTROOT/storage/default/upload.txt"
   1373 
   1374 #
   1375 # Template failure handling
   1376 #
   1377 
   1378 reset_testroot
   1379 write_default_repo_config "ADMIN_USER=bob"
   1380 
   1381 check_status \
   1382   "template failure returns 500" \
   1383   "500 Internal Server Error" \
   1384   env \
   1385     STORAGE_ROOT="$TESTROOT/storage" \
   1386     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
   1387     REMOTE_USER=bob \
   1388     REQUEST_METHOD=GET \
   1389     SIMPLEFILES_ROOT="$TESTROOT/does-not-exist" \
   1390     "$CGI"
   1391 
   1392 check_body \
   1393   "template failure does not return 200" \
   1394   "Template error" \
   1395   env \
   1396     STORAGE_ROOT="$TESTROOT/storage" \
   1397     SIMPLEFILES_CONFIG="$TEST_CONFIG" \
   1398     REMOTE_USER=bob \
   1399     REQUEST_METHOD=GET \
   1400     SIMPLEFILES_ROOT="$TESTROOT/does-not-exist" \
   1401     "$CGI"
   1402 
   1403 ####################################################
   1404 
   1405 #
   1406 # Temporary upload cleanup failure
   1407 #
   1408 
   1409 reset_testroot
   1410 write_default_repo_config "ADMIN_USER=bob"
   1411 
   1412 check_redirect \
   1413   "cleanup failure preserves published upload" \
   1414   "303 See Other" \
   1415   "./" \
   1416   upload_cleanup_failure
   1417 
   1418 check_file \
   1419   "cleanup failure preserves published file" \
   1420   "$TESTROOT/storage/default/cleanup-failure.txt" \
   1421   "published despite cleanup failure"
   1422 
   1423 test_result