diff --git a/configure.ac b/configure.ac index fb32029fe..74a0ab688 100644 --- a/configure.ac +++ b/configure.ac @@ -648,6 +648,8 @@ if test "x$enable_png" != "xno"; then fi AC_SUBST(PNG_LIBS) +LIBCURL_CHECK_CONFIG([], [], [CURL=yes], []) + AC_ARG_WITH(ipv6, [ --with-ipv6=DIR enable IPv6 support. Optional argument specifies location of inet6 libraries.], @@ -2429,6 +2431,7 @@ AC_MSG_RESULT([ CD Audio system :${CDTYPE- no} IPv6 networking : $NETTYPE_IPV6 Compression support: gz=$HAVE_ZLIB ogg=$HAVE_VORBIS flac=$HAVE_FLAC png=$HAVE_PNG + HTTP support : ${CURL-no} Compiler version : $CCVER Compiler flags : $CFLAGS qfcc cpp invocation: $CPP_NAME diff --git a/include/QF/plugin/console.h b/include/QF/plugin/console.h index c6b243475..33291392e 100644 --- a/include/QF/plugin/console.h +++ b/include/QF/plugin/console.h @@ -51,7 +51,7 @@ typedef struct console_func_s { } console_funcs_t; typedef struct console_data_s { - const char *dl_name; + struct dstring_s *dl_name; int *dl_percent; double *realtime; double *frametime; diff --git a/libs/console/client.c b/libs/console/client.c index cff633235..94081abbb 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -594,10 +594,10 @@ draw_download (view_t *view) const char *text; size_t i, j, x, y, n; - if (!con_data.dl_name || !*con_data.dl_name) + if (!con_data.dl_name || !*con_data.dl_name->str) return; - text = QFS_SkipPath(con_data.dl_name); + text = QFS_SkipPath(con_data.dl_name->str); x = con_linewidth - ((con_linewidth * 7) / 40); y = x - strlen (text) - 8; diff --git a/qw/include/Makefile.am b/qw/include/Makefile.am index 473dc596f..7b43e4fbe 100644 --- a/qw/include/Makefile.am +++ b/qw/include/Makefile.am @@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS= foreign EXTRA_DIST = \ - cl_cam.h cl_chat.h cl_demo.h cl_ents.h cl_input.h \ + cl_cam.h cl_chat.h cl_demo.h cl_ents.h cl_http.h cl_input.h \ cl_main.h cl_parse.h cl_pred.h cl_skin.h cl_slist.h cl_tent.h \ client.h crudefile.h game.h host.h map_cfg.h server.h sv_gib.h \ sv_demo.h sv_pr_cmds.h sv_pr_qwe.h sv_progs.h sv_qtv.h sv_recorder.h diff --git a/qw/include/cl_http.h b/qw/include/cl_http.h new file mode 100644 index 000000000..7cd957ec1 --- /dev/null +++ b/qw/include/cl_http.h @@ -0,0 +1,41 @@ +/* + #FILENAME# + + #DESCRIPTION# + + Copyright (C) 2007 #AUTHOR# + + Author: #AUTHOR# + Date: #DATE# + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id: template.h 11394 2007-03-17 03:23:39Z taniwha $ +*/ + +#ifndef __cl_http_h +#define __cl_http_h + +void CL_HTTP_Init (void); +void CL_HTTP_Shutdown (void); +void CL_HTTP_StartDownload (void); +void CL_HTTP_Update (void); +void CL_HTTP_Reset (void); + +#endif//__cl_http_h diff --git a/qw/include/cl_parse.h b/qw/include/cl_parse.h index 5ab36598d..7e8c3def8 100644 --- a/qw/include/cl_parse.h +++ b/qw/include/cl_parse.h @@ -55,6 +55,7 @@ void CL_NewTranslation (int slot, struct skin_s *skin); qboolean CL_CheckOrDownloadFile (const char *filename); qboolean CL_IsUploading(void); void CL_NextUpload(void); +void CL_FinishDownload (void); void CL_StartUpload (byte *data, int size); void CL_StopUpload(void); diff --git a/qw/include/client.h b/qw/include/client.h index 3d1f9cafa..1bd1337ae 100644 --- a/qw/include/client.h +++ b/qw/include/client.h @@ -152,8 +152,9 @@ typedef struct // file transfer from server QFile *download; - char downloadtempname[MAX_OSPATH]; - char downloadname[MAX_OSPATH]; + struct dstring_s *downloadtempname; + struct dstring_s *downloadname; + struct dstring_s *downloadurl; int downloadnumber; dltype_t downloadtype; int downloadpercent; diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 634292fa1..b45a28877 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -117,7 +117,7 @@ client_libs= libqw_client.a libqw_common.a libqw_client_a_SOURCES= \ cl_cam.c cl_chat.c cl_cmd.c cl_cvar.c cl_demo.c cl_ents.c \ - cl_input.c cl_main.c cl_ngraph.c cl_parse.c cl_pred.c \ + cl_http.c cl_input.c cl_main.c cl_ngraph.c cl_parse.c cl_pred.c \ cl_screen.c cl_skin.c cl_slist.c cl_tent.c cl_view.c \ locs.c sbar.c skin.c teamplay.c @@ -135,7 +135,7 @@ qw_client_fbdev_libs= \ $(top_builddir)/libs/video/targets/libQFfbdev.la \ $(client_LIBS) qw_client_fbdev_SOURCES= cl_sys_unix.c -qw_client_fbdev_LDADD= $(qw_client_fbdev_libs) $(NET_LIBS) +qw_client_fbdev_LDADD= $(qw_client_fbdev_libs) $(NET_LIBS) $(LIBCURL) qw_client_fbdev_LDFLAGS= $(common_ldflags) qw_client_fbdev_DEPENDENCIES= $(qw_client_fbdev_libs) @@ -147,7 +147,7 @@ qw_client_mgl_libs= \ $(top_builddir)/libs/video/targets/libQFmgl.la \ $(client_LIBS) qw_client_mgl_SOURCES= cl_sys_win.c -qw_client_mgl_LDADD= $(qw_client_mgl_libs) $(MGL_LIBS) $(NET_LIBS) +qw_client_mgl_LDADD= $(qw_client_mgl_libs) $(MGL_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_mgl_LDFLAGS= $(common_ldflags) qw_client_mgl_DEPENDENCIES= $(qw_client_mgl_libs) @@ -160,7 +160,7 @@ qw_client_sdl_libs= \ $(top_builddir)/libs/video/targets/libQFsdl.la \ $(client_LIBS) qw_client_sdl_SOURCES=sdl_link.c -qw_client_sdl_LDADD= libqw_sdl.a $(qw_client_sdl_libs) $(SDL_LIBS) $(NET_LIBS) +qw_client_sdl_LDADD= libqw_sdl.a $(qw_client_sdl_libs) $(SDL_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_sdl_LDFLAGS= $(common_ldflags) qw_client_sdl_DEPENDENCIES= libqw_sdl.a $(qw_client_sdl_libs) @@ -174,7 +174,7 @@ qw_client_sdl32_libs= \ $(top_builddir)/libs/video/targets/libQFsdl32.la \ $(client_LIBS) qw_client_sdl32_SOURCES=sdl_link.c -qw_client_sdl32_LDADD= libqw_sdl.a $(qw_client_sdl32_libs) $(SDL_LIBS) $(NET_LIBS) +qw_client_sdl32_LDADD= libqw_sdl.a $(qw_client_sdl32_libs) $(SDL_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_sdl32_LDFLAGS=$(common_ldflags) qw_client_sdl32_DEPENDENCIES= libqw_sdl.a $(qw_client_sdl32_libs) @@ -186,7 +186,7 @@ qw_client_svga_libs= \ $(top_builddir)/libs/video/targets/libQFsvga.la \ $(client_LIBS) qw_client_svga_SOURCES= cl_sys_unix.c -qw_client_svga_LDADD= $(qw_client_svga_libs) $(SVGA_LIBS) $(NET_LIBS) +qw_client_svga_LDADD= $(qw_client_svga_libs) $(SVGA_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_svga_LDFLAGS= $(common_ldflags) qw_client_svga_DEPENDENCIES= $(qw_client_svga_libs) @@ -200,7 +200,7 @@ qw_client_x11_libs= \ qw_client_x11_SOURCES= cl_sys_unix.c qw_client_x11_LDADD= $(qw_client_x11_libs) \ $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ - $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) + $(X_EXTRA_LIBS) $(X_SHM_LIB) $(NET_LIBS) $(LIBCURL) qw_client_x11_LDFLAGS= $(common_ldflags) qw_client_x11_DEPENDENCIES= $(qw_client_x11_libs) @@ -219,7 +219,7 @@ qw_client_glx_libs= \ qw_client_glx_SOURCES= cl_sys_unix.c qw_client_glx_LDADD= $(qw_client_glx_libs) \ $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 \ - -lXext $(X_EXTRA_LIBS) $(DL_LIBS) $(NET_LIBS) + -lXext $(X_EXTRA_LIBS) $(DL_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_glx_LDFLAGS= $(common_ldflags) qw_client_glx_DEPENDENCIES= $(qw_client_glx_libs) @@ -232,7 +232,7 @@ qw_client_3dfx_libs= \ $(client_LIBS) qw_client_3dfx_SOURCES= cl_sys_unix.c qw_client_3dfx_LDADD= $(qw_client_3dfx_libs) \ - $(SVGA_LIBS) $(NET_LIBS) + $(SVGA_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_3dfx_LDFLAGS= $(common_ldflags) qw_client_3dfx_DEPENDENCIES= $(qw_client_3dfx_libs) @@ -245,7 +245,7 @@ qw_client_sgl_libs= \ $(top_builddir)/libs/video/targets/libQFsgl.la \ $(client_LIBS) qw_client_sgl_SOURCES=sdl_link.c -qw_client_sgl_LDADD= $(qw_client_sgl_libs) $(SDL_LIBS) $(DL_LIBS) $(NET_LIBS) +qw_client_sgl_LDADD= $(qw_client_sgl_libs) $(SDL_LIBS) $(DL_LIBS) $(NET_LIBS) $(LIBCURL) qw_client_sgl_LDFLAGS= $(common_ldflags) qw_client_sgl_DEPENDENCIES= $(qw_client_sgl_libs) @@ -257,7 +257,7 @@ qw_client_wgl_libs= \ $(top_builddir)/libs/video/targets/libQFwgl.la \ $(client_LIBS) qw_client_wgl_SOURCES= cl_sys_win.c -qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) +qw_client_wgl_LDADD= $(qw_client_wgl_libs) -lgdi32 -lwinmm $(NET_LIBS) $(LIBCURL) qw_client_wgl_LDFLAGS= $(common_ldflags) qw_client_wgl_DEPENDENCIES= $(qw_client_wgl_libs) diff --git a/qw/source/cl_http.c b/qw/source/cl_http.c new file mode 100644 index 000000000..5791768b6 --- /dev/null +++ b/qw/source/cl_http.c @@ -0,0 +1,129 @@ +/* + #FILENAME# + + #DESCRIPTION# + + Copyright (C) 2007 #AUTHOR# + + Author: #AUTHOR# + Date: #DATE# + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((used)) const char rcsid[] = + "$Id: template.c 11394 2007-03-17 03:23:39Z taniwha $"; + +#ifdef HAVE_LIBCURL + +#include + +#include "QF/console.h" +#include "QF/dstring.h" + +#include "cl_http.h" +#include "cl_parse.h" +#include "client.h" + +static int curl_borked; +static CURL *easy_handle; +static CURLM *multi_handle; + +static int +http_progress (void *clientp, double dltotal, double dlnow, + double ultotal, double uplow) +{ + return 0; //non-zero = abort +} + +static size_t +http_write (void *ptr, size_t size, size_t nmemb, void *stream) +{ + if (!cls.download) { + Con_Printf ("http_write: unexpected call\n"); + return -1; + } + return Qwrite (cls.download, ptr, size * nmemb); +} + +void +CL_HTTP_Init (void) +{ + if ((curl_borked = curl_global_init (CURL_GLOBAL_NOTHING))) + return; + multi_handle = curl_multi_init (); +} + +void +CL_HTTP_Shutdown (void) +{ + if (curl_borked) + return; + curl_multi_cleanup (multi_handle); + curl_global_cleanup (); +} + +void +CL_HTTP_StartDownload (void) +{ + easy_handle = curl_easy_init (); + + curl_easy_setopt (easy_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt (easy_handle, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt (easy_handle, CURLOPT_PROGRESSFUNCTION, http_progress); + curl_easy_setopt (easy_handle, CURLOPT_WRITEFUNCTION, http_write); + + curl_easy_setopt (easy_handle, CURLOPT_URL, cls.downloadurl->str); + curl_multi_add_handle (multi_handle, easy_handle); +} + +void +CL_HTTP_Update (void) +{ + int running_handles; + curl_multi_perform (multi_handle, &running_handles); + if (!running_handles) { + curl_multi_remove_handle (multi_handle, easy_handle); + CL_FinishDownload (); + } +} + +void +CL_HTTP_Reset (void) +{ + curl_multi_remove_handle (multi_handle, easy_handle); + curl_easy_cleanup (easy_handle); + easy_handle = 0; +} + +#else + +#include "cl_http.h" + +void CL_HTTP_Init (void) {} +void CL_HTTP_Shutdown (void) {} +void CL_HTTP_StartDownload (void) {} +void CL_HTTP_Update (void) {} +void CL_HTTP_Reset (void) {} + +#endif diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index a7ba5d76d..c48293ab9 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -91,6 +91,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "cl_chat.h" #include "cl_demo.h" #include "cl_ents.h" +#include "cl_http.h" #include "cl_input.h" #include "cl_main.h" #include "cl_parse.h" @@ -500,6 +501,10 @@ CL_Disconnect (void) Cam_Reset (); if (cls.download) { + CL_HTTP_Reset (); + dstring_clearstr (cls.downloadname); + dstring_clearstr (cls.downloadurl); + dstring_clearstr (cls.downloadtempname); Qclose (cls.download); cls.download = NULL; } @@ -659,6 +664,9 @@ CL_AddQFInfoKeys (void) static const char *cap = "pt" #ifdef HAVE_ZLIB "z" +#endif +#ifdef HAVE_LIBCURL + "h" #endif ; @@ -1067,12 +1075,10 @@ CL_Download_f (void) return; } - snprintf (cls.downloadname, sizeof (cls.downloadname), "%s/%s", - qfs_gamedir->dir.def, Cmd_Argv (1)); + dsprintf (cls.downloadname, "%s/%s", qfs_gamedir->dir.def, Cmd_Argv (1)); - strncpy (cls.downloadtempname, cls.downloadname, - sizeof (cls.downloadtempname)); - cls.download = QFS_WOpen (cls.downloadname, 0); + dstring_copystr (cls.downloadtempname, cls.downloadname->str); + cls.download = QFS_WOpen (cls.downloadname->str, 0); if (cls.download) { cls.downloadtype = dl_single; @@ -1549,6 +1555,8 @@ Host_Frame (float time) // fetch results from server CL_ReadPackets (); + if (cls.downloadurl->str) + CL_HTTP_Update (); if (cls.demoplayback2) { player_state_t *self, *oldself; @@ -1741,6 +1749,9 @@ Host_Init (void) pr_gametype = "quakeworld"; cls.userinfo = Info_ParseString ("", MAX_INFO_STRING, 0); + cls.downloadtempname = dstring_newstr (); + cls.downloadname = dstring_newstr (); + cls.downloadurl = dstring_newstr (); cl.serverinfo = Info_ParseString ("", MAX_INFO_STRING, 0); QFS_Init ("qw"); @@ -1799,6 +1810,7 @@ Host_Init (void) sound_precache[i] = cl.sound_name[i]; Net_Log_Init (sound_precache); } + CL_HTTP_Init (); W_LoadWadFile ("gfx.wad"); Key_Init (cl_cbuf); @@ -1882,6 +1894,7 @@ Host_Shutdown (void) Host_WriteConfiguration (); CDAudio_Shutdown (); + CL_HTTP_Shutdown (); NET_Shutdown (); S_Shutdown (); IN_Shutdown (); diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index dc9786205..7fa029289 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -65,6 +65,7 @@ static __attribute__ ((used)) const char rcsid[] = #include "cl_cam.h" #include "cl_chat.h" #include "cl_ents.h" +#include "cl_http.h" #include "cl_input.h" #include "cl_main.h" #include "cl_parse.h" @@ -232,25 +233,24 @@ CL_CheckOrDownloadFile (const char *filename) // ZOID - can't download when recording if (cls.demorecording) { Con_Printf ("Unable to download %s in record mode.\n", - cls.downloadname); + cls.downloadname->str); return true; } // ZOID - can't download when playback if (cls.demoplayback) return true; - strcpy (cls.downloadname, filename); - Con_Printf ("Downloading %s...\n", cls.downloadname); + dstring_copystr (cls.downloadname, filename); + Con_Printf ("Downloading %s...\n", cls.downloadname->str); // download to a temp name, and only rename to the real name when done, // so if interrupted a runt file wont be left - QFS_StripExtension (cls.downloadname, cls.downloadtempname); - strncat (cls.downloadtempname, ".tmp", - sizeof (cls.downloadtempname) - strlen (cls.downloadtempname)); + QFS_StripExtension (cls.downloadname->str, cls.downloadtempname->str); + dstring_appendstr (cls.downloadtempname, ".tmp"); MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, - va ("download \"%s\"", cls.downloadname)); + va ("download \"%s\"", cls.downloadname->str)); cls.downloadnumber++; @@ -416,6 +416,43 @@ CL_RequestNextDownload (void) } } +void +CL_FinishDownload (void) +{ + Qclose (cls.download); + VID_SetCaption (va ("Connecting to %s", cls.servername)); + + // rename the temp file to it's final name + if (strcmp (cls.downloadtempname->str, cls.downloadname->str)) { + dstring_t *oldn = dstring_new (); + dstring_t *newn = dstring_new (); + + if (strncmp (cls.downloadtempname->str, "skins/", 6)) { + dsprintf (oldn, "%s/%s", qfs_gamedir->dir.def, + cls.downloadtempname->str); + dsprintf (newn, "%s/%s", qfs_gamedir->dir.def, + cls.downloadname->str); + } else { + dsprintf (oldn, "%s/%s", qfs_gamedir->dir.skins, + cls.downloadtempname->str + 6); + dsprintf (newn, "%s/%s", qfs_gamedir->dir.skins, + cls.downloadname->str + 6); + } + if (QFS_Rename (oldn->str, newn->str)) + Con_Printf ("failed to rename, %s.\n", strerror (errno)); + dstring_delete (oldn); + dstring_delete (newn); + } + + cls.download = NULL; + dstring_clearstr (cls.downloadname); + dstring_clearstr (cls.downloadurl); + cls.downloadpercent = 0; + + // get another file if needed + CL_RequestNextDownload (); +} + /* CL_ParseDownload @@ -424,7 +461,7 @@ CL_RequestNextDownload (void) static void CL_ParseDownload (void) { - int size, percent, r; + int size, percent; // read the data size = MSG_ReadShort (net_message); @@ -433,7 +470,8 @@ CL_ParseDownload (void) if (cls.demoplayback) { if (size > 0) net_message->readcount += size; - cls.downloadname[0] = 0; + dstring_clearstr (cls.downloadname); + dstring_clearstr (cls.downloadurl); return; // not in demo playback } @@ -444,16 +482,18 @@ CL_ParseDownload (void) Qclose (cls.download); cls.download = NULL; } - cls.downloadname[0] = 0; + dstring_clearstr (cls.downloadname); + dstring_clearstr (cls.downloadurl); CL_RequestNextDownload (); return; } if (size == -2) { - const char *newname = MSG_ReadString (net_message); + const char *newname = MSG_ReadString (net_message); - if (strncmp (newname, cls.downloadname, strlen (cls.downloadname)) - || strstr (newname + strlen (cls.downloadname), "/")) { + if (strncmp (newname, cls.downloadname->str, + strlen (cls.downloadname->str)) + || strstr (newname + strlen (cls.downloadname->str), "/")) { Con_Printf ("WARNING: server tried to give a strange new name: %s\n", newname); @@ -462,10 +502,43 @@ CL_ParseDownload (void) } if (cls.download) { Qclose (cls.download); - unlink (cls.downloadname); + unlink (cls.downloadname->str); } - strncpy (cls.downloadname, newname, sizeof (cls.downloadname)); - Con_Printf ("downloading to %s\n", cls.downloadname); + dstring_copystr (cls.downloadname, newname); + Con_Printf ("downloading to %s\n", cls.downloadname->str); + return; + } + if (size == -3) { +#ifdef HAVE_LIBCURL + const char *url = MSG_ReadString (net_message); + const char *newname = MSG_ReadString (net_message); + + if (newname) { + if (strncmp (newname, cls.downloadname->str, + strlen (cls.downloadname->str)) + || strstr (newname + strlen (cls.downloadname->str), "/")) { + Con_Printf + ("WARNING: server tried to give a strange new name: %s\n", + newname); + CL_RequestNextDownload (); + return; + } + if (cls.download) { + Qclose (cls.download); + unlink (cls.downloadname->str); + } + dstring_copystr (cls.downloadname, newname); + } + dstring_copystr (cls.downloadurl, url); + Con_Printf ("downloading %s to %s\n", cls.downloadurl->str, + cls.downloadname->str); + CL_HTTP_StartDownload (); +#else + MSG_ReadString (net_message); + MSG_ReadString (net_message); + Con_Printf ("server sent http redirect but we don't know how to handle" + "it :(\n"); +#endif return; } // open the file if not opened yet @@ -473,27 +546,28 @@ CL_ParseDownload (void) dstring_t *name = dstring_newstr (); const char *fname, *path; - if (strncmp (cls.downloadtempname, "skins/", 6) == 0) { + if (strncmp (cls.downloadtempname->str, "skins/", 6) == 0) { path = qfs_gamedir->dir.skins; - fname = cls.downloadtempname + 6; - } else if (strncmp (cls.downloadtempname, "progs/", 6) == 0) { + fname = cls.downloadtempname->str + 6; + } else if (strncmp (cls.downloadtempname->str, "progs/", 6) == 0) { path = qfs_gamedir->dir.progs; - fname = cls.downloadtempname + 6; - } else if (strncmp (cls.downloadtempname, "sound/", 6) == 0) { + fname = cls.downloadtempname->str + 6; + } else if (strncmp (cls.downloadtempname->str, "sound/", 6) == 0) { path = qfs_gamedir->dir.sound; - fname = cls.downloadtempname + 6; - } else if (strncmp (cls.downloadtempname, "maps/", 5) == 0) { + fname = cls.downloadtempname->str + 6; + } else if (strncmp (cls.downloadtempname->str, "maps/", 5) == 0) { path = qfs_gamedir->dir.maps; - fname = cls.downloadtempname + 5; + fname = cls.downloadtempname->str + 5; } else { path = qfs_gamedir->dir.def; - fname = cls.downloadtempname; + fname = cls.downloadtempname->str; } dsprintf (name, "%s/%s", path, fname); cls.download = QFS_WOpen (name->str, 0); if (!cls.download) { - cls.downloadname[0] = 0; + dstring_clearstr (cls.downloadname); + dstring_clearstr (cls.downloadurl); net_message->readcount += size; Con_Printf ("Failed to open %s\n", name->str); CL_RequestNextDownload (); @@ -509,43 +583,14 @@ CL_ParseDownload (void) if (percent != 100) { // request next block if (percent != cls.downloadpercent) - VID_SetCaption (va ("Downloading %s %d%%", cls.downloadname, + VID_SetCaption (va ("Downloading %s %d%%", cls.downloadname->str, percent)); cls.downloadpercent = percent; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); SZ_Print (&cls.netchan.message, "nextdl"); } else { - char oldn[MAX_OSPATH]; - char newn[MAX_OSPATH]; - - Qclose (cls.download); - VID_SetCaption (va ("Connecting to %s", cls.servername)); - - // rename the temp file to it's final name - if (strcmp (cls.downloadtempname, cls.downloadname)) { - if (strncmp (cls.downloadtempname, "skins/", 6)) { - snprintf (oldn, sizeof (oldn), "%s/%s", qfs_gamedir->dir.def, - cls.downloadtempname); - snprintf (newn, sizeof (newn), "%s/%s", qfs_gamedir->dir.def, - cls.downloadname); - } else { - snprintf (oldn, sizeof (oldn), "%s/%s", qfs_gamedir->dir.skins, - cls.downloadtempname + 6); - snprintf (newn, sizeof (newn), "%s/%s", qfs_gamedir->dir.skins, - cls.downloadname + 6); - } - r = QFS_Rename (oldn, newn); - if (r) - Con_Printf ("failed to rename, %s.\n", strerror (errno)); - } - - cls.download = NULL; - cls.downloadname[0] = 0; - cls.downloadpercent = 0; - - // get another file if needed - CL_RequestNextDownload (); + CL_FinishDownload (); } }