//unfortunately, have to wrap the docs in a C comment for doxygen
// vim:tw=74:formatoptions-=l
/**
\page qw_download_spec QW Download Specification

client has 'h' flag in "*cap" info string

format of svc_download message:
\verbatim
<size (short)> <percent (byte)> ([url (string)] [newname (string)] | [data])
\endverbatim

size and percent are always present.

url is present only for http redirects.

data is present only when size is > 0 (ie, normal downloading)

newname is present for all http redirects (but may be the empty string) or if
the file to download has a different name to what what requested. This is so
the client saves the downloaded file with the correct name (in QF, this is
currently used for gzipped transfers, but there are plans to enable whole pak
downloads (similar to RTCW and ET)).

size is the number of data bytes in the message (if >= 0) or a special flag:
\li -1  file not found. download aborted
\li -2  download filename is not what was requested (in QF, this is because
        the file has been gzipped and has the .gz extension). In this case,
        newname is in the message. Currently, QF checks newname to ensure the
        only modification is the addition of an extension.
\li -3  http redirect. url is always present and is the full url to download.
        If the download name is the same as the requested name, newname will
        be the empty string (""), otherwise it contains the new name of the
        file. See -2.

QF \#defines for the above values:
\verbatim
#define DL_NOFILE       -1
#define DL_RENAME       -2
#define DL_HTTP         -3
\endverbatim

Pseudo-code representing client side handling of svc_download
\verbatim
CL_ParseDownload
{
    size = MSG_ReadShort (net_message);
    percent = MSG_ReadByte (net_message);
    if (size == DL_NOFILE) {
        abort download
        return
    }
    if (size == DL_RENAME) {
        newname = MSG_ReadString (net_message);
        if (newname is bad) {
            abort download
            return
        }
        rename file
        return
    }
    if (size == DL_HTTP) {
        url = MSG_ReadString (net_message);
        newname = MSG_ReadString (net_message);
        if (newname != "") {
            if (newname is bad) {
                abort download
                return
            }
            rename file
        }
        start http transfer
        return
    }
    normal download processing
}
\endverbatim

\note While the QF quakeworld server simply appends the requested file's path
to the given url base, with the addition of a '/' (eg, "maps/foo.map" to
"http://server/downloads", giving "http://server/downloads/maps/foo.map"), so
long as it is reasonable for the client to not rename the download file, there
is no requirement for the full url to match the requested name in any manner,
and newname can be left as empty (""). However, if the client must rename the
file, set newname to the new name. The extension checking is done as a
security measure.

\note Currently, the only reason QF renames a download is if it found eg
"maps/foo.map.gz" instead of "maps/foo.map" (2:1 to 3:1 compression on maps is
nice). This is the basis of the extension checking the QF clients do.

\todo [this has no bearing on the protocol itself]
One good reason for the name being quite different is when the requested file
is part of a pak file (and downloading the pak file is permitted), the entire
pak file can be sent instead. QF does not yet do this, but it should be easy
enough to implement: if file_from_pak (from FOpenFile) is set, and pak file
downloading is permitted, do a rename (-2 for non-http, set newname in http)
and send that instead. The client can check for a ".pak" extension in the
rename, permit it, and then cause a rescan of the game directory in order to
pick up the new pak file.
*/
