/** * @brief Opens the specified URL and minimizes the game window. You have to specify the whole * url including the protocol. */ static void CL_OpenURL_f (void) { if (Cmd_Argc() != 2) { Com_Printf("usage: %s <url>\n", Cmd_Argv(0)); return; } VID_Minimize(); Sys_OpenURL(Cmd_Argv(1)); }
/** * @brief A download message has been received from the server */ void CL_ParseDownload(msg_t *msg) { int size; unsigned char data[MAX_MSGLEN]; int block; if (!*cls.download.downloadTempName) { Com_Printf("Server sending download, but no download was requested\n"); CL_AddReliableCommand("stopdl"); return; } // read the data block = MSG_ReadShort(msg); // unfortunately DLTYPE_WWW is -1 FIXME: change this someday! //if (block < 0) //{ //Com_Error(ERR_DROP, "CL_ParseDownload: Server sending invalid download data"); //} // www dl, if we haven't acknowledged the download redirect yet if (block == DLTYPE_WWW) { if (!cls.download.bWWWDl) { // server is sending us a www download Q_strncpyz(cls.download.originalDownloadName, cls.download.downloadName, sizeof(cls.download.originalDownloadName)); Q_strncpyz(cls.download.downloadName, MSG_ReadString(msg), sizeof(cls.download.downloadName)); cls.download.downloadSize = MSG_ReadLong(msg); cls.download.downloadFlags = MSG_ReadLong(msg); if (cls.download.downloadFlags & (1 << DL_FLAG_URL)) { Sys_OpenURL(cls.download.downloadName, qtrue); Cbuf_ExecuteText(EXEC_APPEND, "quit\n"); CL_AddReliableCommand("wwwdl bbl8r"); // not sure if that's the right msg cls.download.bWWWDlAborting = qtrue; return; } Cvar_SetValue("cl_downloadSize", cls.download.downloadSize); Com_DPrintf("Server redirected download: %s\n", cls.download.downloadName); cls.download.bWWWDl = qtrue; // activate wwwdl client loop CL_AddReliableCommand("wwwdl ack"); // make sure the server is not trying to redirect us again on a bad checksum if (strstr(cls.download.badChecksumList, va("@%s", cls.download.originalDownloadName))) { Com_Printf("refusing redirect to %s by server (bad checksum)\n", cls.download.downloadName); CL_AddReliableCommand("wwwdl fail"); cls.download.bWWWDlAborting = qtrue; return; } // make downloadTempName an OS path Q_strncpyz(cls.download.downloadTempName, FS_BuildOSPath(Cvar_VariableString("fs_homepath"), cls.download.downloadTempName, ""), sizeof(cls.download.downloadTempName)); cls.download.downloadTempName[strlen(cls.download.downloadTempName) - 1] = '\0'; if (!DL_BeginDownload(cls.download.downloadTempName, cls.download.downloadName)) { // setting bWWWDl to false after sending the wwwdl fail doesn't work // not sure why, but I suspect we have to eat all remaining block -1 that the server has sent us // still leave a flag so that CL_WWWDownload is inactive // we count on server sending us a gamestate to start up clean again CL_AddReliableCommand("wwwdl fail"); cls.download.bWWWDlAborting = qtrue; Com_Printf("Failed to initialize download for '%s'\n", cls.download.downloadName); } // Check for a disconnected download // we'll let the server disconnect us when it gets the bbl8r message if (cls.download.downloadFlags & (1 << DL_FLAG_DISCON)) { CL_AddReliableCommand("wwwdl bbl8r"); cls.download.bWWWDlDisconnected = qtrue; } return; } else { // server keeps sending that message till we acknowledge it, eat and ignore //MSG_ReadLong( msg ); MSG_ReadString(msg); MSG_ReadLong(msg); MSG_ReadLong(msg); return; } } if (!block) { // block zero is special, contains file size cls.download.downloadSize = MSG_ReadLong(msg); Cvar_SetValue("cl_downloadSize", cls.download.downloadSize); if (cls.download.downloadSize < 0) { Com_Error(ERR_DROP, "%s", MSG_ReadString(msg)); return; } } size = MSG_ReadShort(msg); if (size < 0 || size > sizeof(data)) { Com_Error(ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk.", size); return; } MSG_ReadData(msg, data, size); if (cls.download.downloadBlock != block) { Com_DPrintf("CL_ParseDownload: Expected block %d, got %d\n", cls.download.downloadBlock, block); return; } // open the file if not opened yet if (!cls.download.download) { cls.download.download = FS_SV_FOpenFileWrite(cls.download.downloadTempName); if (!cls.download.download) { Com_Printf("Could not create %s\n", cls.download.downloadTempName); CL_AddReliableCommand("stopdl"); Com_NextDownload(); return; } } if (size) { FS_Write(data, size, cls.download.download); } CL_AddReliableCommand(va("nextdl %d", cls.download.downloadBlock)); cls.download.downloadBlock++; cls.download.downloadCount += size; // So UI gets access to it Cvar_SetValue("cl_downloadCount", cls.download.downloadCount); if (!size) // A zero length block means EOF { if (cls.download.download) { FS_FCloseFile(cls.download.download); cls.download.download = 0; // rename the file FS_SV_Rename(cls.download.downloadTempName, cls.download.downloadName); } *cls.download.downloadTempName = *cls.download.downloadName = 0; Cvar_Set("cl_downloadName", ""); // send intentions now // We need this because without it, we would hold the last nextdl and then start // loading right away. If we take a while to load, the server is happily trying // to send us that last block over and over. // Write it twice to help make sure we acknowledge the download CL_WritePacket(); CL_WritePacket(); // get another file if needed Com_NextDownload(); } }