Patch title: Release 87 bulk changes
Abstract:
File: /pliant/appli/file_browser.pli
Key:
    Removed line
    Added line
   
module "/pliant/protocol/http/server.pli"
module "/pliant/protocol/http/style/default.style"
module "/pliant/protocol/common/mime.pli"
module "/pliant/language/context.pli"
module "/pliant/language/compiler.pli"
module "/pliant/language/stream.pli"
module "/pliant/admin/file.pli"
module "/pliant/admin/execute.pli"
module "/pliant/util/encoding/http.pli"
module "/pliant/protocol/http/server.pli"
module "/pliant/protocol/http/style/default.style"
module "/pliant/protocol/common/mime.pli"
module "/pliant/language/context.pli"
module "/pliant/language/compiler.pli"
module "/pliant/language/stream.pli"
module "/pliant/admin/file.pli"
module "/pliant/admin/execute.pli"
module "/pliant/util/encoding/http.pli"
module "/pliant/util/encoding/date.pli"
module "/pliant/protocol/http/webdav.pli"
if os_api="linux"
  module "/pliant/language/stream/pipe.pli"



module "/pliant/protocol/http/webdav.pli"
if os_api="linux"
  module "/pliant/language/stream/pipe.pli"



method page browse_directory path options write
  arg_rw HtmlPage page ; arg Str path options ; arg CBool wr
method page browse_directory path options write direct_path
  arg_rw HtmlPage page ; arg Str path options ; arg CBool write ; arg Str direct_path
  implicit page
    if options="delete" and write
      [Are you sure that you want to delete directory] ; fix
      button "yes" noeol
        file_tree_delete path
        goto_backward
      button "no"
        goto_backward
    eif options="list"
  implicit page
    if options="delete" and write
      [Are you sure that you want to delete directory] ; fix
      button "yes" noeol
        file_tree_delete path
        goto_backward
      button "no"
        goto_backward
    eif options="list"
      var Array:FileInfo files := file_list path standard+re
      var Array:FileInfo files := file_list path extended+relative+directories
      for (var Int i) 0 files:size-1
        html "<pfile name=[dq]"+(html_encode files:i:name)+"
    else
      head "<meta name=[dq]robots[dq] content=[dq]noindex,no
      var CBool detailed := (options option "detailed") and 
      title path
      table columns 2 border 0
        cell [Path:]
        cell (fixed text:path)
      if not detailed and allowed:"administrator"
        link "compute disk usage" "./" options "detailed"
      for (var Int i) 0 files:size-1
        html "<pfile name=[dq]"+(html_encode files:i:name)+"
    else
      head "<meta name=[dq]robots[dq] content=[dq]noindex,no
      var CBool detailed := (options option "detailed") and 
      title path
      table columns 2 border 0
        cell [Path:]
        cell (fixed text:path)
      if not detailed and allowed:"administrator"
        link "compute disk usage" "./" options "detailed"
      var Array:FileInfo files := file_list path standard+re
      var Array:FileInfo files := file_list path extended+relative+directories+sorted
      var Int total_count := 0 ; var Intn total_size := 0 
      var Int total_count := 0 ; var Intn total_size := 0 
      table columns (shunt detailed 6 5)
      table columns (shunt detailed 5 4)
        cell header
          bold [name]
        if detailed
          cell header
            bold [count]
        cell header
          bold [size]
        cell header
          bold [date ]
          note "*"
            title "Pliant date format"
            [The date is displayed using] ; fixed [ ] ; ital
        cell header
          void
        cell header
          bold [name]
        if detailed
          cell header
            bold [count]
        cell header
          bold [size]
        cell header
          bold [date ]
          note "*"
            title "Pliant date format"
            [The date is displayed using] ; fixed [ ] ; ital
        cell header
          void
        cell header
          void
        for (var Int i) 0 files:size-1
          var Pointer:FileInfo f :> files i
          html "<pfile name=[dq]"+(html_encode f:name)+"[dq]
          if f:is_directory
            cell
              bold
        for (var Int i) 0 files:size-1
          var Pointer:FileInfo f :> files i
          html "<pfile name=[dq]"+(html_encode f:name)+"[dq]
          if f:is_directory
            cell
              bold
                link f:name (replace (http_encode f:name) "%
                link f:name f:name
            if detailed
              path_size path+f:name (var Int count) (var Int
              cell
                italic (text string:count)
              cell
                if (options option "byte")
                  italic (text string:size)
                else
                  italic (text (string size\2^20)+" MB")
              total_count += count ; total_size += size
            else
              cell void
            cell void
            cell
              small
                if (file_list path+f:name standard+directori
            if detailed
              path_size path+f:name (var Int count) (var Int
              cell
                italic (text string:count)
              cell
                if (options option "byte")
                  italic (text string:size)
                else
                  italic (text (string size\2^20)+" MB")
              total_count += count ; total_size += size
            else
              cell void
            cell void
            cell
              small
                if (file_list path+f:name standard+directori
                  link "delete" (http_encode f:name) no_exte
            cell void
                  link "delete" f:name no_extension options "delete"
          else
            cell
          else
            cell
              link f:name (http_encode f:name) no_extension
              if direct_path<>""
                link f:name direct_path+f:name no_extension
              else
                text f:name
            if detailed
              cell void
            cell
              text (string f:size "separated [dq]"+character
            cell
              text (string f:datetime)
            cell
              small
                var Str mime := query_mime_type f:extension
                if not (mime parse "binary/" any) and not (m
            if detailed
              cell void
            cell
              text (string f:size "separated [dq]"+character
            cell
              text (string f:datetime)
            cell
              small
                var Str mime := query_mime_type f:extension
                if not (mime parse "binary/" any) and not (m
                  link "view" (http_encode f:name) no_extens
                  link "view" f:name no_extension options "text" ; fixed [ ]
                  if write
                  if write
                    link "edit" (http_encode f:name) no_exte
                link "download" (http_encode f:name) no_exte
                    link "edit" f:name no_extension options "edit" ; fixed [ ]
                link "download" f:name no_extension options "binary" ; fixed [ ] 
                if write
                if write
                  link "copy" (http_encode f:name) no_extens
                  link "delete" (http_encode f:name) no_exte
            cell
              var Str vp := virtual_path
              virtual_path := path+f:name
              execute_dynamic_page "pliant:/pliant/appli/fil
              virtual_path := vp
                  link "copy" f:name no_extension options "copy" ; fixed [ ] 
                  link "delete" f:name no_extension options "delete"
            total_count += 1 ; total_size += f size
        if detailed
          cell header
            [total]
          cell
            italic (text string:total_count)
          cell
            if (options option "byte")
              italic (text string:total_size)
            else
              italic (text (string total_size\2^20)+" MB")
          cell void
          cell void
            total_count += 1 ; total_size += f size
        if detailed
          cell header
            [total]
          cell
            italic (text string:total_count)
          cell
            if (options option "byte")
              italic (text string:total_size)
            else
              italic (text (string total_size\2^20)+" MB")
          cell void
          cell void
          cell void
      if write
        if os_api="linux" and allowed:"administrator"
          input "" (var Str subdirs) noeol
          note "*"
            [Leave the field blank if you want to download t
          page button ".tgz download"
            stream_pipe (var Str in_pipe_name) (var Str out_
            thread
              execute "tar -zc "+(shunt subdirs<>"" subdirs 
            (var Stream tgz) open in_pipe_name in+safe
            reset_http_answer
      if write
        if os_api="linux" and allowed:"administrator"
          input "" (var Str subdirs) noeol
          note "*"
            [Leave the field blank if you want to download t
          page button ".tgz download"
            stream_pipe (var Str in_pipe_name) (var Str out_
            thread
              execute "tar -zc "+(shunt subdirs<>"" subdirs 
            (var Stream tgz) open in_pipe_name in+safe
            reset_http_answer
            var Pointer:HttpRequest request :> page http_req
            request answer_mime_type := "binary/*"
            request answer_is_dynamic := true
            request send_header
            while not tgz:atend and request:stream=success
              raw_copy tgz request:stream 1 2^16
            request send_footer
            http_request send_header "mime [dq]binary/*[dq]"
            while not tgz:atend and http_request:answer_stream=success
              raw_copy tgz http_request:answer_stream 1 2^16
            http_request send_footer
        file_upload "" (var Str filename) noeol
        button "Upload" noeol
          if (file_query filename standard)=defined
            var Str remote := filename option "remote_name" 
            if remote<>""
              apply_uploaded_file filename path+remote ""
              reload_page
            else
              [I have not received the file name !]
          else
            [I have not received the file !]
            para
              [The explaination might be that your browser d
              [If you wonder what browsers supports uploadin
        if os_api="linux" and allowed:"administrator"
          page button ".tgz upload" noeol
            var Str tgz := replace file_temporary ".tmp" ".t
            file_move filename tgz
            file_extract tgz path
            file_delete tgz
            reload_page
        eol
        input "" (var Str filename2) noeol
        button "Create file" noeol
          (var Stream s) open path+filename2 out+safe ; s cl
          reload_page
        button "Create directory"
          file_tree_create path+filename2+"/"
          reload_page
        # input "Target computer: " (var Str target) noeol
        # input "Password: " (var Str passwd) password noeol
        # button "Synchronize"
        #   void
        if allowed:"administrator"
          page button "Delete directory"
            title "Delete "+path+" directory"
            para
              [Here is the list of the files you are going t
        file_upload "" (var Str filename) noeol
        button "Upload" noeol
          if (file_query filename standard)=defined
            var Str remote := filename option "remote_name" 
            if remote<>""
              apply_uploaded_file filename path+remote ""
              reload_page
            else
              [I have not received the file name !]
          else
            [I have not received the file !]
            para
              [The explaination might be that your browser d
              [If you wonder what browsers supports uploadin
        if os_api="linux" and allowed:"administrator"
          page button ".tgz upload" noeol
            var Str tgz := replace file_temporary ".tmp" ".t
            file_move filename tgz
            file_extract tgz path
            file_delete tgz
            reload_page
        eol
        input "" (var Str filename2) noeol
        button "Create file" noeol
          (var Stream s) open path+filename2 out+safe ; s cl
          reload_page
        button "Create directory"
          file_tree_create path+filename2+"/"
          reload_page
        # input "Target computer: " (var Str target) noeol
        # input "Password: " (var Str passwd) password noeol
        # button "Synchronize"
        #   void
        if allowed:"administrator"
          page button "Delete directory"
            title "Delete "+path+" directory"
            para
              [Here is the list of the files you are going t
              var Array:FileInfo files2 := file_list path st
              var Array:FileInfo files2 := file_list path standard+recursive+sorted
              var Intn total := 0
              for (var Int i) 0 files2:size-1
                fixed (text files2:i:name) ; eol
                total += files2:i size
              text "That's "+(string files2:size)+" files co
            para
              [Are you sure that you want to recursively del
              fixed (text " "+path+" ")
              [?]
            para
              button "yes" noeol
                file_tree_delete path
                goto_backward
              button "no"
                goto_backward
      table columns 1
        cell
          table columns 2 border 0
            cell
              input "Name pattern: " (var Str name_pattern)
              if allowed:"administrator"
                input "Content pattern: " (var Str content_p
                select "Case sensitive: " (var Str case_sens
                  option "no" ""
                  option "yes" "yes"
            cell
              button "Search"
                title "Files search report"
                table columns 2 border 0
                  cell [Path:]
                  cell (fixed text:path)
                  if name_pattern<>""
                    cell [Name pattern:]
                    cell (fixed text:name_pattern)
                  if content_pattern<>""
                    cell [Content pattern:]
                    cell (fixed text:content_pattern)
              var Intn total := 0
              for (var Int i) 0 files2:size-1
                fixed (text files2:i:name) ; eol
                total += files2:i size
              text "That's "+(string files2:size)+" files co
            para
              [Are you sure that you want to recursively del
              fixed (text " "+path+" ")
              [?]
            para
              button "yes" noeol
                file_tree_delete path
                goto_backward
              button "no"
                goto_backward
      table columns 1
        cell
          table columns 2 border 0
            cell
              input "Name pattern: " (var Str name_pattern)
              if allowed:"administrator"
                input "Content pattern: " (var Str content_p
                select "Case sensitive: " (var Str case_sens
                  option "no" ""
                  option "yes" "yes"
            cell
              button "Search"
                title "Files search report"
                table columns 2 border 0
                  cell [Path:]
                  cell (fixed text:path)
                  if name_pattern<>""
                    cell [Name pattern:]
                    cell (fixed text:name_pattern)
                  if content_pattern<>""
                    cell [Content pattern:]
                    cell (fixed text:content_pattern)
                var Array:FileInfo all_files := file_list pa
                var Array:FileInfo all_files := file_list path standard+relative+directories+recursive+sorted
                var CBool case := case_sensitive="yes"
                if content_pattern<>"" and allowed:"administ
                  table columns 2
                    for (var Int i) 0 all_files:size-1
                      if name_pattern="" or (all_files:i:nam
                        (var Stream s) open path+all_files:i
                        while not s:atend
                          var Str l := s readline
                          var CBool matching
                          if case
                            matching := (l search content_pa
                          else
                            matching := (upper:l search uppe
                          if matching
                            cell
                              link all_files:i:name all_file
                            cell
                              small
                                fixed text:l ; eol
                                while not s:atend
                                  var Str l := s readline
                                  if case
                                    matching := (l search co
                                  else
                                    matching := (upper:l sea
                                  if matching
                                    fixed text:l ; eol
                else
                  for (var Int i) 0 all_files:size-1
                    if name_pattern="" or (all_files:i:name_
                      link all_files:i:name all_files:i:path


method page browse_file path options write
  arg_rw HtmlPage page ; arg Str path options ; arg CBool wr
  implicit page
                var CBool case := case_sensitive="yes"
                if content_pattern<>"" and allowed:"administ
                  table columns 2
                    for (var Int i) 0 all_files:size-1
                      if name_pattern="" or (all_files:i:nam
                        (var Stream s) open path+all_files:i
                        while not s:atend
                          var Str l := s readline
                          var CBool matching
                          if case
                            matching := (l search content_pa
                          else
                            matching := (upper:l search uppe
                          if matching
                            cell
                              link all_files:i:name all_file
                            cell
                              small
                                fixed text:l ; eol
                                while not s:atend
                                  var Str l := s readline
                                  if case
                                    matching := (l search co
                                  else
                                    matching := (upper:l sea
                                  if matching
                                    fixed text:l ; eol
                else
                  for (var Int i) 0 all_files:size-1
                    if name_pattern="" or (all_files:i:name_
                      link all_files:i:name all_files:i:path


method page browse_file path options write
  arg_rw HtmlPage page ; arg Str path options ; arg CBool wr
  implicit page
    if options="view"
    if options="text"
      reset_http_answer
      reset_http_answer
      http_request send_static_file path "filter_ascii"
      http_request send_static_file path "mime [dq]text/plain[dq]"
    eif options="binary"
      reset_http_answer
      http_request send_static_file path "mime [dq]binary/*[dq]"
    eif options="edit" and write
      small
        bold text:path
        var FileInfo info := file_query path extended
        if info:link<>""
          text " -> "+info:link
        html (repeat 5 "&nbsp;")
        text (string info:size)+" bytes last modifyed on "+(
        eol
      var Str all := ""
      (var Stream s1) open path in+safe
      while not s1:atend
        all += s1:readline+"[lf]"
      text_input "" all columns 80 rows 35
      button "Update "+(path (path search_last "/" -1)+1 pat
        (var Stream s2) open path out+safe
        s2 writechars all
        goto_backward
    eif options="edit" and write
      small
        bold text:path
        var FileInfo info := file_query path extended
        if info:link<>""
          text " -> "+info:link
        html (repeat 5 "&nbsp;")
        text (string info:size)+" bytes last modifyed on "+(
        eol
      var Str all := ""
      (var Stream s1) open path in+safe
      while not s1:atend
        all += s1:readline+"[lf]"
      text_input "" all columns 80 rows 35
      button "Update "+(path (path search_last "/" -1)+1 pat
        (var Stream s2) open path out+safe
        s2 writechars all
        goto_backward
    eif options="download"
      reset_http_answer
      http_request send_static_file path "filter_binary"
    eif options="copy" and write
      [Move ] ; fixed:(text " "+path+" ")
      input " to: " (var Str to)
      button "Copy" noeol
        var Str dest := to
        if (dest 0 1)<>"/" and (dest search ":" -1)=(-1)
          dest := (path 0 (path search_last "/" -1)+1)+dest
        else
          requires "administrator"
        if (reverse:dest 0 1)="/"
          dest += path (path search_last "/" path:len)+1 pat
        file_copy path dest
        goto_backward
      button "Move" noeol
        var Str dest := to
        if (dest 0 1)<>"/" and (dest search ":" -1)=(-1)
          dest := (path 0 (path search_last "/" -1)+1)+dest
        else
          requires "administrator"
        if (reverse:dest 0 1)="/"
          dest += path (path search_last "/" path:len)+1 pat
        file_move path dest
        goto_backward
      button "Cancel"
        goto_backward
    eif options="delete" and write
      [Are you sure that you want to delete file] ; fixed:(t
      button "yes" noeol
        file_delete path
        goto_backward
      button "no"
        goto_backward
    else
    eif options="copy" and write
      [Move ] ; fixed:(text " "+path+" ")
      input " to: " (var Str to)
      button "Copy" noeol
        var Str dest := to
        if (dest 0 1)<>"/" and (dest search ":" -1)=(-1)
          dest := (path 0 (path search_last "/" -1)+1)+dest
        else
          requires "administrator"
        if (reverse:dest 0 1)="/"
          dest += path (path search_last "/" path:len)+1 pat
        file_copy path dest
        goto_backward
      button "Move" noeol
        var Str dest := to
        if (dest 0 1)<>"/" and (dest search ":" -1)=(-1)
          dest := (path 0 (path search_last "/" -1)+1)+dest
        else
          requires "administrator"
        if (reverse:dest 0 1)="/"
          dest += path (path search_last "/" path:len)+1 pat
        file_move path dest
        goto_backward
      button "Cancel"
        goto_backward
    eif options="delete" and write
      [Are you sure that you want to delete file] ; fixed:(t
      button "yes" noeol
        file_delete path
        goto_backward
      button "no"
        goto_backward
    else
      # var Str ext := path (path search_last "." path:len) 
      # if addressof:(query_mime_dynamic_filter ext)=address
      reset_http_answer
      reset_http_answer
      http_request send_static_file path options
      http_request send_static_file path ""




method page file_browser path options write
  arg_rw HtmlPage page ; arg Str path options ; arg CBool wr
method page file_browser path options write direct_path
  arg_rw HtmlPage page ; arg Str path options ; arg CBool write ; arg Str direct_path
  implicit page
    var Str answer := ""
    if virtual_command="GET" or virtual_command="POST"
      if path:len>0 and (path path:len-1)="/"
  implicit page
    var Str answer := ""
    if virtual_command="GET" or virtual_command="POST"
      if path:len>0 and (path path:len-1)="/"
        browse_directory http_decode:path options write
        browse_directory path options write direct_path
      else
      else
        browse_file http_decode:path options write
        browse_file path options write
    eif virtual_command="HEAD"
    eif virtual_command="HEAD"
      var FileInfo info := file_query http_decode:path exten
      var FileInfo info := file_query path extended
      if info=success
        reset_http_answer
        if not info:is_directory
          http_request answer_size := info size
          http_request answer_datetime := info datetime
        http_request answer_is_dynamic := false
        http_request send_header
        http_request send_footer
      else
        answer := "404 Not found"
    eif virtual_command="PUT"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      if info=success
        reset_http_answer
        if not info:is_directory
          http_request answer_size := info size
          http_request answer_datetime := info datetime
        http_request answer_is_dynamic := false
        http_request send_header
        http_request send_footer
      else
        answer := "404 Not found"
    eif virtual_command="PUT"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      var DateTime dt := undefined
      var Str opt := ""
      var Pointer:Arrow c :> http_request:query_log first
      while c<>null
        var Pointer:Str s :> c map Str
      var Str opt := ""
      var Pointer:Arrow c :> http_request:query_log first
      while c<>null
        var Pointer:Str s :> c map Str
        if (s parse word:"Pliant-Options" ":" any:(var Str v
        if (s parse acword:"pliant-options" ":" any:(var Str value))
          opt := http_decode value
          opt := http_decode value
        eif (s parse acword:"last-modified" ":" any:(var Str value))
          dt := rfc1123_date value
        c :> http_request:query_log next c
      var Str temp := file_temporary
        c :> http_request:query_log next c
      var Str temp := file_temporary
      http_request read_data_file undefined temp
      answer := shunt (apply_uploaded_file temp http_decode:
      reset_http_answer
      (var Stream data) open temp out+safe
      var Int bytes := 0
      while not http_request:query_stream:atend and data=success
        bytes += raw_copy http_request:query_stream data 1 2^24
      data close
      if dt=defined
        file_configure temp "datetime "+string:dt
      answer := shunt (apply_uploaded_file temp path opt)=success "200 OK" "500 Could not write file"
      file_delete temp
    eif virtual_command="OPTIONS"
      answer := "200 OK"
      http_request:answer_extra append addressof:(new Str "A
      file_delete temp
    eif virtual_command="OPTIONS"
      answer := "200 OK"
      http_request:answer_extra append addressof:(new Str "A
      http_request:answer_extra append addressof:(new Str "D
      http_request:answer_extra append addressof:(new Str "DAV: 1,2")
    eif virtual_command="PROPFIND"
    eif virtual_command="PROPFIND"
      var Str slash ; var FileInfo info
      if path:len=0 or (path path:len-1)<>"/"
        slash := "/"
        info := file_query http_decode:path+slash extended
        if info=failure
          slash := ""
          info := file_query http_decode:path extended
      else
        slash := ""
        info := file_query http_decode:path extended
      if info=success
        var Int depth := undefined
        var Pointer:Arrow c :> http_request:query_log first
        while c<>null
          var Pointer:Str s :> c map Str
          if (s parse acword:"Depth" ":" (var Int i))
            depth := i
          c :> http_request:query_log next c
        var Array:FileInfo files
        if depth>0
          files := file_list http_decode:path+slash extended
        else
          files size := 1
          files 0 := info
          files:0 name := ""
        http_request read_data_string 2^16 (var Str query)
        var List:Str query_list ; query_list += query
        webdav_list http_request:url_path+slash files query_
        var Int size := 0
        var Pointer:Str l :> answer_list first
        while exists:l
          size += l:len+2
          l :> answer_list next l
        reset_http_answer
        http_request answer_status := "207 Multi-Status"
        http_request answer_mime_type := ""
        http_request answer_size := size
        http_request answer_is_dynamic := false
        http_request answer_datetime := undefined
        http_request send_header
        var Pointer:Str l :> answer_list first
        while exists:l
          http_request:stream writechars l
          http_request:stream writechars "[cr][lf]"
          l :> answer_list next l
        http_request send_footer
        if true
          (var Stream log) open "embedded:/tmp/webdav.txt" o
          var Pointer:Str l :> query_list first
          while exists:l
            log writeline l
            l :> query_list next l
          log writeline ""
          var Pointer:Str l :> answer_list first
          while exists:l
            log writeline l
            l :> answer_list next l
          log close
      else
        answer := "404 Not found"
      var FileInfo info := file_query path extended
      var Array:FileInfo dir
      if http_request:webdav_depth<>0
        dir := file_list info:name extended+directories+relative+sorted
      webdav_propfind info dir
    eif virtual_command="PROPPATCH" or virtual_command="LOCK" or virtual_command="UNLOCK"
      answer := "200 OK"
    eif virtual_command="MKCOL"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      var Str slash := shunt path:len=0 or (path path:len-1)
    eif virtual_command="MKCOL"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      var Str slash := shunt path:len=0 or (path path:len-1)
      answer := shunt (file_tree_create http_decode:path+sla
      answer := shunt (file_tree_create path+slash)=success "200 OK" "500 Could not create directory"
    eif virtual_command="MOVE"
      answer := "403 Forbidden"
    eif virtual_command="MOVE"
      answer := "403 Forbidden"
      var Str src := "http://"+http_request:site_name+http_r
      var Str src := "http://"+http_request:site_name+http_request:encoded_path
      var Str dest := ""
      var Pointer:Arrow c :> http_request:query_log first
      while c<>null
        if ((c map Str) parse acword:"Destination" ":" any:(
          dest := value
        c :> http_request:query_log next c
      if (dest 0 (dest search_last "/" dest:len)+1)=(src 0 (
        var Status status := file_move path (path 0 (path se
        if status=success
          answer := "200 OK"
    eif virtual_command="DELETE"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      var Str dest := ""
      var Pointer:Arrow c :> http_request:query_log first
      while c<>null
        if ((c map Str) parse acword:"Destination" ":" any:(
          dest := value
        c :> http_request:query_log next c
      if (dest 0 (dest search_last "/" dest:len)+1)=(src 0 (
        var Status status := file_move path (path 0 (path se
        if status=success
          answer := "200 OK"
    eif virtual_command="DELETE"
      if not write
        reset_http_answer
        http_request send_authentification_request
        return
      answer := shunt (file_delete http_decode:path)=success
      answer := shunt file_delete:path=success or (file_tree_delete path+"/")=success "200 OK" "404 No such file"
    else
      answer := "501 Not implemented"
    if answer<>""
      reset_http_answer
    else
      answer := "501 Not implemented"
    if answer<>""
      reset_http_answer
      http_request answer_status := answer
      http_request answer_mime_type := ""
      http_request answer_size := 0
      if virtual_command="OPTIONS"
        http_request answer_is_dynamic := false
        http_request answer_datetime := undefined
      http_request send_header
      http_request send_header "status "+string:answer+" size 0 static"
      http_request send_footer

export '. apply_uploaded_file' '. file_browser'
      http_request send_footer

export '. apply_uploaded_file' '. file_browser'