Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @Echo Off
- Set DB=%__ServerRoot%\data\uploads.db
- Set Data=%*
- :Next
- For /F "tokens=1,* delims=;" %%A In ("%Data%") Do (
- For /F "tokens=1,2 delims==" %%C In ("%%A") Do (Set $%%C=%%D)
- If Not "%%B"=="" Set Data=%%B&GoTo :Next
- )
- :: Проверки
- If Not Defined $key (Set "Message=Не указан ключ" & Call :Die 403)
- If Not Exist "%~dp0%$key%\." (Set "Message=Этот файл приватный и ваш ключ неправильный" & Call :Die 403)
- :: Информация о файле
- For /F "eol= tokens=1-3 delims=|" %%A In ('Echo SELECT `filename`^, `filesize_bytes`^, `timestamp` FROM `uploads` WHERE `key` like "%$key%"^;^|sqlite3 "%DB%"') Do (
- Set "name=%%A"
- Set "size=%%B"
- Set "timestamp=%%C"
- )
- :: Проверки
- If Not Exist "%~dp0%$key%\%name%" (Set "Message=Файл не найден" & Call :Die 404)
- :: Меняем кодировку для имени файла, на случай если он содержит кириллицу
- Set "_$name=%name%"
- For /F "eol= tokens=1,* delims==" %%A In ('Set _$name^|recode cp866..utf8') Do Set "nameUTF8=%%B"
- :: Конвертируем время для Last-Modified
- For /F "delims=" %%A In ('UnixTime2HTTPDate %timestamp%') Do (Set timestamp=%%A)
- :: Получаем текущее время
- For /F "delims=" %%A In ('GetHTTPDate') Do (Set datetime=%%A)
- :: Получаем MIME-тип из расширения
- For /F "delims=" %%A In ('GetMIMEType "%name%"') Do Set "mimetype=%%A"
- :: Если указан Range переходим к обработчику запроса
- If Defined H-Range GoTo :Range
- :: Отдаём заголовки и файл, если не поступало запросов на частичную отдачу
- Echo HTTP/1.0 200 OK
- Echo Server: OWS/%__OWS_version%
- Echo Date: %datetime%
- Echo Accept-Ranges: bytes
- Echo Content-Type: %mimetype%
- Echo Content-Length: %size%
- Echo Content-Disposition: attachment; filename="%nameUTF8%"; size=%size%; creation-date=%timestamp%; modification-date=%timestamp%; read-date=%datetime%;
- Echo Date: %datetime%
- Echo Last-Modified: %timestamp%
- Echo Connection: close
- Echo.
- Type "%~dp0%$key%\%name%"
- Exit
- :Range
- SetLocal EnableDelayedExpansion
- :: Случайная строка для использования в качестве разделителя
- For /F "delims=" %%A In ('RandomID 16') Do (Set boundary=%%A)
- :: Максимальное значение диапазона - размер-1байт
- For /F "delims=" %%- In ('cc %size%-1') Do Set MaxRange=%%-
- :: Имя временного файла, используемого если в одном запросе несколько диапазонов
- Set TmpFile="%Temp%\~part%boundary%.tmp"
- :: Выделяем диапазоны из заголовка, если тип не bytes - отдаём HTTP 416
- For /F "tokens=1,* delims==" %%A In ("%H-Range%") Do If /I "%%A"=="bytes" (Set "Ranges=%%B") Else (Call :Err416)
- Set Parts=0
- For %%A In (%Ranges%) Do (
- Set rejected=false
- Set Range="%%A"
- For /F "tokens=1,2 delims=-" %%B In ("!Range:-="-"!") Do (
- Set "rMin=%%~B"
- Set "rMax=%%~C"
- :: Разворачиваем диапазоны с пустыми значениями
- If "!rMax!"=="" Set rMax=%MaxRange%
- cc !rMax! ^>= %size%|ExitCode&&Set rMax=%MaxRange%
- If "!rMin!"=="" For /F "delims=" %%- In ('cc %MaxRange%-!rMax!+1') Do (
- Set rMax=%MaxRange%
- Set rMin=%%-
- )
- )
- :: Проверки
- If Not Defined rMin Set rejected=true
- If Not Defined rMax Set rejected=true
- cc !rMin! ^<= !rMax!|ExitCode||Set rejected=true
- :: Если диапазон проходит по всем условиям, записываем аргументы для функции, выдающей часть файла
- If "!rejected!"=="false" (
- Set /A Parts+=1
- Set $Range=!rMin!-!rMax!/%size%
- Set Skip=!rMin!
- For /F "delims=" %%- In ('cc !rMax!+1-!rMin!') Do Set Length=%%-
- Set Part[!Parts!]="!Skip!" "!Length!" "!$Range!" "%boundary%" "!Parts!"
- )
- )
- :: Есть заголовок Range, но ни один из диапазонов невалиден? Отдаём HTTP 416
- If "%Parts%"=="0" Call :Err416
- :: Начинаем отдавать заголовок
- Echo HTTP/1.1 206 Partial Content
- Echo Server: OWS/%__OWS_version%
- Echo Date: %datetime%
- Echo Last-Modified: %timestamp%
- Echo Accept-Ranges: bytes
- If "%Parts%"=="1" (
- Echo Content-Type: %mimetype%
- ) Else (
- Echo Content-Type: multipart/byteranges; boundary=%boundary%
- )
- If "%Parts%"=="1" (
- Echo Content-Length: !Length!
- Echo Content-Range: bytes !rMin!-!rMax!/%size%
- Echo.
- Call :PartialContent %Part[1]% "1"
- ) Else (
- For /L %%A In (1,1,!Parts!) Do (
- Call :PartialContent !Part[%%A]! !Parts!>>%TmpFile%
- )
- :: Подсчитываем размер получившихся частей ВМЕСТЕ с заголовками и разделителями
- Call :PartsSize %TmpFile%
- Echo.
- rem Выводим контент и удаляем временный файл
- Type "%TmpFile%"
- Del "%TmpFile%" 2>nul
- )
- EndLocal
- Exit
- :: Выдаём часть файла согласно аргументам
- :PartialContent (skip, length, range, boundary, part, parts)
- If "%__Debug%"=="true" (
- Echo [%Time%] %~nx0: %H-REQUEST_METHOD% %H-REQUEST_URI% Range: %H-Range%
- Echo Skip: "%~1", Length: "%~2", Range: "%~3" --%~4-- [%~5 of %~6]
- )>>"%__DebugLogFile%"
- :: Костыль для tail
- For /F "delims=" %%+ In ('cc %~1+1') Do Set tSkip=%%+
- If "%~6"=="1" (
- tail --bytes=+!tSkip! "%~dp0%$key%\%name%!!|%~2
- Exit /B
- )
- Echo --%~4
- Echo Content-Type: %mimetype%
- Echo Content-Range: bytes %~3
- Echo.
- tail --bytes=+!tSkip! "%~dp0%$key%\%name%!!|%~2
- If "%~5"=="%~6" <nul Set /P "Echo=--%~4--"
- Exit /B
- :PartsSize (file)
- For %%A In ("%~1") Do Echo Content-Length: %%~zA
- Exit /B
- :Err416
- Echo HTTP/1.1 416 Range Not Satisfiable
- Echo Server: OWS/%__OWS_version%
- Echo Date: %datetime%
- Echo Accept-Ranges: bytes
- Echo Content-Range: bytes */%size%
- Echo.
- Exit
- :Die
- If "%~1"=="403" Echo HTTP/1.0 403 Forbidden
- If "%~1"=="404" Echo HTTP/1.0 404 Not Found
- Echo Server: OWS/%__OWS_version%
- Echo Content-Type: text/html;charset=UTF-8
- Echo Connection: close
- Echo.
- Echo.%Message%
- Exit
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement