예제 #1
0
void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack)
{
	prvm_prog_t *prog = SVVM_prog;
	char name[MAX_QPATH];

	if(client->sv_demo_file != NULL)
		return; // we already have a demo

	strlcpy(name, filename, sizeof(name));
	FS_DefaultExtension(name, ".dem", sizeof(name));

	Con_Printf("Recording demo for # %d (%s) to %s\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress, name);

	// Reset discardable flag for every new demo.
	PRVM_serveredictfloat(client->edict, discardabledemo) = 0;

	client->sv_demo_file = FS_OpenRealFile(name, "wb", false);
	if(!client->sv_demo_file)
	{
		Con_Print("ERROR: couldn't open.\n");
		return;
	}

	FS_Printf(client->sv_demo_file, "%i\n", forcetrack);
}
예제 #2
0
/*
====================
CL_CutDemo

Dumps the current demo to a buffer, and resets the demo to its starting point.
Used to insert csprogs.dat files as a download to the beginning of a demo file.
====================
*/
void CL_CutDemo (unsigned char **buf, fs_offset_t *filesize)
{
	*buf = NULL;
	*filesize = 0;

	FS_Close(cls.demofile);
	*buf = FS_LoadFile(cls.demoname, tempmempool, false, filesize);

	// restart the demo recording
	cls.demofile = FS_OpenRealFile(cls.demoname, "wb", false);
	if(!cls.demofile)
		Sys_Error("failed to reopen the demo file");
	FS_Printf(cls.demofile, "%i\n", cls.forcetrack);
}
예제 #3
0
파일: keys.c 프로젝트: Blub/darkplaces
static void Key_History_Shutdown(void)
{
	// TODO write history to a file

	qfile_t *historyfile = FS_OpenRealFile("darkplaces_history.txt", "w", false);
	if(historyfile)
	{
		int i;
		for(i = 0; i < CONBUFFER_LINES_COUNT(&history); ++i)
			FS_Printf(historyfile, "%s\n", ConBuffer_GetLine(&history, i));
		FS_Close(historyfile);
	}

	ConBuffer_Shutdown(&history);
}
예제 #4
0
static void Key_History_Shutdown(void)
{
	// TODO write history to a file

// not necessary for mobile
#ifndef DP_MOBILETOUCH
	qfile_t *historyfile = FS_OpenRealFile("darkplaces_history.txt", "w", false);
	if(historyfile)
	{
		int i;
		for(i = 0; i < CONBUFFER_LINES_COUNT(&history); ++i)
			FS_Printf(historyfile, "%s\n", ConBuffer_GetLine(&history, i));
		FS_Close(historyfile);
	}
#endif

	ConBuffer_Shutdown(&history);
}
예제 #5
0
static void Key_History_Init(void)
{
	qfile_t *historyfile;
	ConBuffer_Init(&history, HIST_TEXTSIZE, HIST_MAXLINES, zonemempool);

// not necessary for mobile
#ifndef DP_MOBILETOUCH
	historyfile = FS_OpenRealFile("darkplaces_history.txt", "rb", false); // rb to handle unix line endings on windows too
	if(historyfile)
	{
		char buf[MAX_INPUTLINE];
		int bufpos;
		int c;

		bufpos = 0;
		for(;;)
		{
			c = FS_Getc(historyfile);
			if(c < 0 || c == 0 || c == '\r' || c == '\n')
			{
				if(bufpos > 0)
				{
					buf[bufpos] = 0;
					ConBuffer_AddLine(&history, buf, bufpos, 0);
					bufpos = 0;
				}
				if(c < 0)
					break;
			}
			else
			{
				if(bufpos < MAX_INPUTLINE - 1)
					buf[bufpos++] = c;
			}
		}

		FS_Close(historyfile);
	}
#endif

	history_line = -1;
}
예제 #6
0
파일: sv_demo.c 프로젝트: Blub/darkplaces
void SV_StartDemoRecording(client_t *client, const char *filename, int forcetrack)
{
	char name[MAX_QPATH];

	if(client->sv_demo_file != NULL)
		return; // we already have a demo

	strlcpy(name, filename, sizeof(name));
	FS_DefaultExtension(name, ".dem", sizeof(name));

	Con_Printf("Recording demo for # %d (%s) to %s\n", PRVM_NUM_FOR_EDICT(client->edict), client->netaddress, name);

	client->sv_demo_file = FS_OpenRealFile(name, "wb", false);
	if(!client->sv_demo_file)
	{
		Con_Print("ERROR: couldn't open.\n");
		return;
	}

	FS_Printf(client->sv_demo_file, "%i\n", forcetrack);
}
예제 #7
0
/*
===============
Host_SaveConfig_f

Writes key bindings and archived cvars to config.cfg
===============
*/
static void Host_SaveConfig_to(const char *file)
{
	qfile_t *f;

// dedicated servers initialize the host but don't parse and set the
// config.cfg cvars
	// LordHavoc: don't save a config if it crashed in startup
	if (host_framecount >= 3 && cls.state != ca_dedicated && !COM_CheckParm("-benchmark") && !COM_CheckParm("-capturedemo"))
	{
		f = FS_OpenRealFile(file, "wb", false);
		if (!f)
		{
			Con_Printf("Couldn't write %s.\n", file);
			return;
		}

		Key_WriteBindings (f);
		Cvar_WriteVariables (f);

		FS_Close (f);
	}
}
예제 #8
0
파일: cap_ogg.c 프로젝트: Blub/darkplaces
void SCR_CaptureVideo_Ogg_BeginVideo(void)
{
	cls.capturevideo.format = CAPTUREVIDEOFORMAT_OGG_VORBIS_THEORA;
	cls.capturevideo.formatextension = "ogv";
	cls.capturevideo.videofile = FS_OpenRealFile(va("%s.%s", cls.capturevideo.basename, cls.capturevideo.formatextension), "wb", false);
	cls.capturevideo.endvideo = SCR_CaptureVideo_Ogg_EndVideo;
	cls.capturevideo.videoframes = SCR_CaptureVideo_Ogg_VideoFrames;
	cls.capturevideo.soundframe = SCR_CaptureVideo_Ogg_SoundFrame;
	cls.capturevideo.formatspecific = Mem_Alloc(tempmempool, sizeof(capturevideostate_ogg_formatspecific_t));
	{
		LOAD_FORMATSPECIFIC_OGG();
		int num, denom, i;
		ogg_page pg;
		ogg_packet pt, pt2, pt3;
		theora_comment tc;
		vorbis_comment vc;
		theora_info ti;

		format->serial1 = rand();
		qogg_stream_init(&format->to, format->serial1);

		if(cls.capturevideo.soundrate)
		{
			do
			{
				format->serial2 = rand();
			}
			while(format->serial1 == format->serial2);
			qogg_stream_init(&format->vo, format->serial2);
		}

		format->videopage.len = format->audiopage.len = 0;

		qtheora_info_init(&ti);
		ti.frame_width = cls.capturevideo.width;
		ti.frame_height = cls.capturevideo.height;
		ti.width = (ti.frame_width + 15) & ~15;
		ti.height = (ti.frame_height + 15) & ~15;
		//ti.offset_x = ((ti.width - ti.frame_width) / 2) & ~1;
		//ti.offset_y = ((ti.height - ti.frame_height) / 2) & ~1;

		for(i = 0; i < 2; ++i)
		{
			format->yuv[i].y_width = ti.width;
			format->yuv[i].y_height = ti.height;
			format->yuv[i].y_stride = ti.width;
			format->yuv[i].uv_width = ti.width / 2;
			format->yuv[i].uv_height = ti.height / 2;
			format->yuv[i].uv_stride = ti.width / 2;
			format->yuv[i].y = (unsigned char *) Mem_Alloc(tempmempool, format->yuv[i].y_stride * format->yuv[i].y_height);
			format->yuv[i].u = (unsigned char *) Mem_Alloc(tempmempool, format->yuv[i].uv_stride * format->yuv[i].uv_height);
			format->yuv[i].v = (unsigned char *) Mem_Alloc(tempmempool, format->yuv[i].uv_stride * format->yuv[i].uv_height);
		}
		format->yuvi = -1; // -1: no frame valid yet, write into 0

		FindFraction(cls.capturevideo.framerate / cls.capturevideo.framestep, &num, &denom, 1001);
		ti.fps_numerator = num;
		ti.fps_denominator = denom;

		FindFraction(1 / vid_pixelheight.value, &num, &denom, 1000);
		ti.aspect_numerator = num;
		ti.aspect_denominator = denom;

		ti.colorspace = OC_CS_UNSPECIFIED;
		ti.pixelformat = OC_PF_420;

		ti.quick_p = true; // http://mlblog.osdir.com/multimedia.ogg.theora.general/2004-07/index.shtml
		ti.dropframes_p = false;

		ti.target_bitrate = cl_capturevideo_ogg_theora_bitrate.integer * 1000;
		ti.quality = cl_capturevideo_ogg_theora_quality.integer;

		if(ti.target_bitrate <= 0)
		{
			if(ti.quality < 0)
			{
				ti.target_bitrate = -1;
				ti.keyframe_data_target_bitrate = (unsigned int)-1;
				ti.quality = 63;
			}
			else
			{
				ti.target_bitrate = -1;
				ti.keyframe_data_target_bitrate = (unsigned int)-1;
				ti.quality = bound(0, ti.quality, 63);
			}
		}
		else
		{
			if(ti.quality < 0)
			{
				ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
				ti.keyframe_data_target_bitrate = (int) (ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value));
				ti.quality = -1;
			}
			else
			{
				ti.target_bitrate = bound(45000, ti.target_bitrate, 2000000);
				ti.keyframe_data_target_bitrate = (int) (ti.target_bitrate * max(1, cl_capturevideo_ogg_theora_keyframe_bitrate_multiplier.value));
				ti.quality = -1;
			}
		}

		// this -1 magic is because ti.keyframe_frequency and ti.keyframe_mindistance use different metrics
		ti.keyframe_frequency = bound(1, cl_capturevideo_ogg_theora_keyframe_maxinterval.integer, 1000);
		ti.keyframe_mindistance = bound(1, cl_capturevideo_ogg_theora_keyframe_mininterval.integer, (int) ti.keyframe_frequency) - 1;
		ti.noise_sensitivity = bound(0, cl_capturevideo_ogg_theora_noise_sensitivity.integer, 6);
		ti.sharpness = bound(0, cl_capturevideo_ogg_theora_sharpness.integer, 2);
		ti.keyframe_auto_threshold = bound(0, cl_capturevideo_ogg_theora_keyframe_auto_threshold.integer, 100);

		ti.keyframe_frequency_force = ti.keyframe_frequency;
		ti.keyframe_auto_p = (ti.keyframe_frequency != ti.keyframe_mindistance + 1);

		qtheora_encode_init(&format->ts, &ti);
		qtheora_info_clear(&ti);

		// vorbis?
		if(cls.capturevideo.soundrate)
		{
			qvorbis_info_init(&format->vi);
			qvorbis_encode_init_vbr(&format->vi, cls.capturevideo.soundchannels, cls.capturevideo.soundrate, bound(-1, cl_capturevideo_ogg_vorbis_quality.value, 10) * 0.099);
			qvorbis_comment_init(&vc);
			qvorbis_analysis_init(&format->vd, &format->vi);
			qvorbis_block_init(&format->vd, &format->vb);
		}

		qtheora_comment_init(&tc);

		/* create the remaining theora headers */
		qtheora_encode_header(&format->ts, &pt);
		qogg_stream_packetin(&format->to, &pt);
		if (qogg_stream_pageout (&format->to, &pg) != 1)
			fprintf (stderr, "Internal Ogg library error.\n");
		FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
		FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);

		qtheora_encode_comment(&tc, &pt);
		qogg_stream_packetin(&format->to, &pt);
		qtheora_encode_tables(&format->ts, &pt);
		qogg_stream_packetin (&format->to, &pt);

		qtheora_comment_clear(&tc);

		if(cls.capturevideo.soundrate)
		{
			qvorbis_analysis_headerout(&format->vd, &vc, &pt, &pt2, &pt3);
			qogg_stream_packetin(&format->vo, &pt);
			if (qogg_stream_pageout (&format->vo, &pg) != 1)
				fprintf (stderr, "Internal Ogg library error.\n");
			FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
			FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);

			qogg_stream_packetin(&format->vo, &pt2);
			qogg_stream_packetin(&format->vo, &pt3);

			qvorbis_comment_clear(&vc);
		}

		for(;;)
		{
			int result = qogg_stream_flush (&format->to, &pg);
			if (result < 0)
				fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
			if (result <= 0)
				break;
			FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
			FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
		}

		if(cls.capturevideo.soundrate)
		for(;;)
		{
			int result = qogg_stream_flush (&format->vo, &pg);
			if (result < 0)
				fprintf (stderr, "Internal Ogg library error.\n"); // TODO Host_Error
			if (result <= 0)
				break;
			FS_Write(cls.capturevideo.videofile, pg.header, pg.header_len);
			FS_Write(cls.capturevideo.videofile, pg.body, pg.body_len);
		}
	}
}
예제 #9
0
/*
====================
CL_Record_f

record <demoname> <map> [cd track]
====================
*/
void CL_Record_f (void)
{
	int c, track;
	char name[MAX_OSPATH];
	char vabuf[1024];

	c = Cmd_Argc();
	if (c != 2 && c != 3 && c != 4)
	{
		Con_Print("record <название> [<карта> [дорожка cd]]\n");
		return;
	}

	if (strstr(Cmd_Argv(1), ".."))
	{
		Con_Print("Относительные пути не разрешены.\n");
		return;
	}

	if (c == 2 && cls.state == ca_connected)
	{
		Con_Print("Нельзя записать - уже подключен к серверу\nЗапись деморолика клиентом нужно начинать до подключения\n");
		return;
	}

	if (cls.state == ca_connected)
		CL_Disconnect();

	// write the forced cd track number, or -1
	if (c == 4)
	{
		track = atoi(Cmd_Argv(3));
		Con_Printf("Меняем CD-дорожку на %i\n", cls.forcetrack);
	}
	else
		track = -1;

	// get the demo name
	strlcpy (name, Cmd_Argv(1), sizeof (name));
	FS_DefaultExtension (name, ".dem", sizeof (name));

	// start the map up
	if (c > 2)
		Cmd_ExecuteString ( va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(2)), src_command, false);

	// open the demo file
	Con_Printf("записываю в %s.\n", name);
	cls.demofile = FS_OpenRealFile(name, "wb", false);
	if (!cls.demofile)
	{
		Con_Print("ОШИБКА: не могу открыть файл.\n");
		return;
	}
	strlcpy(cls.demoname, name, sizeof(cls.demoname));

	cls.forcetrack = track;
	FS_Printf(cls.demofile, "%i\n", cls.forcetrack);

	cls.demorecording = true;
	cls.demo_lastcsprogssize = -1;
	cls.demo_lastcsprogscrc = -1;
}
예제 #10
0
/*
====================
Curl_Begin

Starts a download of a given URL to the file name portion of this URL (or name
if given) in the "dlcache/" folder.
====================
*/
static qboolean Curl_Begin(const char *URL, const char *extraheaders, double maxspeed, const char *name, qboolean ispak, qboolean forthismap, const char *post_content_type, const unsigned char *postbuf, size_t postbufsize, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata)
{
	if(!curl_dll)
	{
		return false;
	}
	else
	{
		char fn[MAX_OSPATH];
		char urlbuf[1024];
		const char *p, *q;
		size_t length;
		downloadinfo *di;

		// if URL is protocol:///* or protocol://:port/*, insert the IP of the current server
		p = strchr(URL, ':');
		if(p)
		{
			if(!strncmp(p, ":///", 4) || !strncmp(p, "://:", 4))
			{
				char addressstring[128];
				*addressstring = 0;
				InfoString_GetValue(cls.userinfo, "*ip", addressstring, sizeof(addressstring));
				q = strchr(addressstring, ':');
				if(!q)
					q = addressstring + strlen(addressstring);
				if(*addressstring)
				{
					dpsnprintf(urlbuf, sizeof(urlbuf), "%.*s://%.*s%s", (int) (p - URL), URL, (int) (q - addressstring), addressstring, URL + (p - URL) + 3);
					URL = urlbuf;
				}
			}
		}

		// Note: This extraction of the file name portion is NOT entirely correct.
		//
		// It does the following:
		//
		//   http://host/some/script.cgi/SomeFile.pk3?uid=ABCDE -> SomeFile.pk3
		//   http://host/some/script.php?uid=ABCDE&file=/SomeFile.pk3 -> SomeFile.pk3
		//   http://host/some/script.php?uid=ABCDE&file=SomeFile.pk3 -> script.php
		//
		// However, I'd like to keep this "buggy" behavior so that PHP script
		// authors can write download scripts without having to enable
		// AcceptPathInfo on Apache. They just have to ensure that their script
		// can be called with such a "fake" path name like
		// http://host/some/script.php?uid=ABCDE&file=/SomeFile.pk3
		//
		// By the way, such PHP scripts should either send the file or a
		// "Location:" redirect; PHP code example:
		//
		//   header("Location: http://www.example.com/");
		//
		// By the way, this will set User-Agent to something like
		// "Nexuiz build 22:27:55 Mar 17 2006" (engineversion) and Referer to
		// dp://serverhost:serverport/ so you can filter on this; an example
		// httpd log file line might be:
		//
		//   141.2.16.3 - - [17/Mar/2006:22:32:43 +0100] "GET /maps/tznex07.pk3 HTTP/1.1" 200 1077455 "dp://141.2.16.7:26000/" "Nexuiz Linux 22:07:43 Mar 17 2006"

		if(!name)
			name = CleanURL(URL);

		if(!buf)
		{
			p = strrchr(name, '/');
			p = p ? (p+1) : name;
			q = strchr(p, '?');
			length = q ? (size_t)(q - p) : strlen(p);
			dpsnprintf(fn, sizeof(fn), "dlcache/%.*s", (int)length, p);

			name = fn; // make it point back

			// already downloading the file?
			{
				downloadinfo *di = Curl_Find(fn);
				if(di)
				{
					Con_Printf("Can't download %s, already getting it from %s!\n", fn, CleanURL(di->url));

					// however, if it was not for this map yet...
					if(forthismap && !di->forthismap)
					{
						di->forthismap = true;
						// this "fakes" a download attempt so the client will wait for
						// the download to finish and then reconnect
						++numdownloads_added;
					}

					return false;
				}
			}

			if(ispak && FS_FileExists(fn))
			{
				qboolean already_loaded;
				if(FS_AddPack(fn, &already_loaded, true))
				{
					Con_DPrintf("%s already exists, not downloading!\n", fn);
					if(already_loaded)
						Con_DPrintf("(pak was already loaded)\n");
					else
					{
						if(forthismap)
						{
							++numdownloads_added;
							++numdownloads_success;
						}
					}

					return false;
				}
				else
				{
					qfile_t *f = FS_OpenRealFile(fn, "rb", false);
					if(f)
					{
						char buf[4] = {0};
						FS_Read(f, buf, sizeof(buf)); // no "-1", I will use memcmp

						if(memcmp(buf, "PK\x03\x04", 4) && memcmp(buf, "PACK", 4))
						{
							Con_DPrintf("Detected non-PAK %s, clearing and NOT resuming.\n", fn);
							FS_Close(f);
							f = FS_OpenRealFile(fn, "wb", false);
							if(f)
								FS_Close(f);
						}
						else
						{
							// OK
							FS_Close(f);
						}
					}
				}
			}
		}

		// if we get here, we actually want to download... so first verify the
		// URL scheme (so one can't read local files using file://)
		if(strncmp(URL, "http://", 7) && strncmp(URL, "ftp://", 6) && strncmp(URL, "https://", 8))
		{
			Con_Printf("Curl_Begin(\"%s\"): nasty URL scheme rejected\n", URL);
			return false;
		}

		if(forthismap)
			++numdownloads_added;
		di = (downloadinfo *) Z_Malloc(sizeof(*di));
		strlcpy(di->filename, name, sizeof(di->filename));
		strlcpy(di->url, URL, sizeof(di->url));
		dpsnprintf(di->referer, sizeof(di->referer), "dp://%s/", cls.netcon ? cls.netcon->address : "notconnected.invalid");
		di->forthismap = forthismap;
		di->stream = NULL;
		di->startpos = 0;
		di->curle = NULL;
		di->started = false;
		di->ispak = (ispak && !buf);
		di->maxspeed = maxspeed;
		di->bytes_received = 0;
		di->bytes_received_curl = 0;
		di->bytes_sent_curl = 0;
		di->extraheaders = extraheaders;
		di->next = downloads;
		di->prev = NULL;
		if(di->next)
			di->next->prev = di;

		di->buffer = buf;
		di->buffersize = bufsize;
		if(callback == NULL)
		{
			di->callback = curl_default_callback;
			di->callback_data = di;
		}
		else
		{
			di->callback = callback;
			di->callback_data = cbdata;
		}

		if(post_content_type)
		{
			di->post_content_type = post_content_type;
			di->postbuf = postbuf;
			di->postbufsize = postbufsize;
		}
		else
		{
			di->post_content_type = NULL;
			di->postbuf = NULL;
			di->postbufsize = 0;
		}

		downloads = di;
		return true;
	}
}
예제 #11
0
/*
====================
CheckPendingDownloads

checks if there are free download slots to start new downloads in.
To not start too many downloads at once, only one download is added at a time,
up to a maximum number of cl_curl_maxdownloads are running.
====================
*/
static void CheckPendingDownloads(void)
{
	const char *h;
	if(!curl_dll)
		return;
	if(numdownloads < cl_curl_maxdownloads.integer)
	{
		downloadinfo *di;
		for(di = downloads; di; di = di->next)
		{
			if(!di->started)
			{
				if(!di->buffer)
				{
					Con_Printf("Downloading %s -> %s", CleanURL(di->url), di->filename);

					di->stream = FS_OpenRealFile(di->filename, "ab", false);
					if(!di->stream)
					{
						Con_Printf("\nFAILED: Could not open output file %s\n", di->filename);
						Curl_EndDownload(di, CURL_DOWNLOAD_FAILED, CURLE_OK);
						return;
					}
					FS_Seek(di->stream, 0, SEEK_END);
					di->startpos = FS_Tell(di->stream);

					if(di->startpos > 0)
						Con_Printf(", resuming from position %ld", (long) di->startpos);
					Con_Print("...\n");
				}
				else
				{
					Con_DPrintf("Downloading %s -> memory\n", CleanURL(di->url));
					di->startpos = 0;
				}

				di->curle = qcurl_easy_init();
				di->slist = NULL;
				qcurl_easy_setopt(di->curle, CURLOPT_URL, di->url);
				qcurl_easy_setopt(di->curle, CURLOPT_USERAGENT, engineversion);
				qcurl_easy_setopt(di->curle, CURLOPT_REFERER, di->referer);
				qcurl_easy_setopt(di->curle, CURLOPT_RESUME_FROM, (long) di->startpos);
				qcurl_easy_setopt(di->curle, CURLOPT_FOLLOWLOCATION, 1);
				qcurl_easy_setopt(di->curle, CURLOPT_WRITEFUNCTION, CURL_fwrite);
				qcurl_easy_setopt(di->curle, CURLOPT_LOW_SPEED_LIMIT, (long) 256);
				qcurl_easy_setopt(di->curle, CURLOPT_LOW_SPEED_TIME, (long) 45);
				qcurl_easy_setopt(di->curle, CURLOPT_WRITEDATA, (void *) di);
				qcurl_easy_setopt(di->curle, CURLOPT_PRIVATE, (void *) di);
				qcurl_easy_setopt(di->curle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP);
				if(qcurl_easy_setopt(di->curle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP) != CURLE_OK)
				{
					Con_Printf("^1WARNING:^7 for security reasons, please upgrade to libcurl 7.19.4 or above. In a later version of DarkPlaces, HTTP redirect support will be disabled for this libcurl version.\n");
					//qcurl_easy_setopt(di->curle, CURLOPT_FOLLOWLOCATION, 0);
				}
				if(di->post_content_type)
				{
					qcurl_easy_setopt(di->curle, CURLOPT_POST, 1);
					qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDS, di->postbuf);
					qcurl_easy_setopt(di->curle, CURLOPT_POSTFIELDSIZE, di->postbufsize);
					di->slist = qcurl_slist_append(di->slist, va("Content-Type: %s", di->post_content_type));
				}

				// parse extra headers into slist
				// \n separated list!
				h = di->extraheaders;
				while(h)
				{
					const char *hh = strchr(h, '\n');
					if(hh)
					{
						char *buf = (char *) Mem_Alloc(tempmempool, hh - h + 1);
						memcpy(buf, h, hh - h);
						buf[hh - h] = 0;
						di->slist = qcurl_slist_append(di->slist, buf);
						h = hh + 1;
					}
					else
					{
						di->slist = qcurl_slist_append(di->slist, h);
						h = NULL;
					}
				}

				qcurl_easy_setopt(di->curle, CURLOPT_HTTPHEADER, di->slist);

				
				qcurl_multi_add_handle(curlm, di->curle);
				di->started = true;
				++numdownloads;
				if(numdownloads >= cl_curl_maxdownloads.integer)
					break;
			}
		}
	}
}
예제 #12
0
static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error)
{
	qboolean ok = false;
	if(!curl_dll)
		return;
	switch(status)
	{
		case CURL_DOWNLOAD_SUCCESS:
			ok = true;
			di->callback(CURLCBSTATUS_OK, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_FAILED:
			di->callback(CURLCBSTATUS_FAILED, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_ABORTED:
			di->callback(CURLCBSTATUS_ABORTED, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_SERVERERROR:
			// reopen to enforce it to have zero bytes again
			if(di->stream)
			{
				FS_Close(di->stream);
				di->stream = FS_OpenRealFile(di->filename, "wb", false);
			}

			if(di->callback)
				di->callback(error ? (int) error : CURLCBSTATUS_SERVERERROR, di->bytes_received, di->buffer, di->callback_data);
			break;
		default:
			if(di->callback)
				di->callback(CURLCBSTATUS_UNKNOWN, di->bytes_received, di->buffer, di->callback_data);
			break;
	}

	if(di->curle)
	{
		qcurl_multi_remove_handle(curlm, di->curle);
		qcurl_easy_cleanup(di->curle);
		if(di->slist)
			qcurl_slist_free_all(di->slist);
	}

	if(!di->callback && ok && !di->bytes_received)
	{
		Con_Printf("ERROR: empty file\n");
		ok = false;
	}

	if(di->stream)
		FS_Close(di->stream);

	if(ok && di->ispak)
	{
		ok = FS_AddPack(di->filename, NULL, true);
		if(!ok)
		{
			// pack loading failed?
			// this is critical
			// better clear the file again...
			di->stream = FS_OpenRealFile(di->filename, "wb", false);
			FS_Close(di->stream);

			if(di->startpos && !di->callback)
			{
				// this was a resume?
				// then try to redownload it without reporting the error
				Curl_Begin(di->url, di->extraheaders, di->maxspeed, di->filename, di->ispak, di->forthismap, di->post_content_type, di->postbuf, di->postbufsize, NULL, 0, NULL, NULL);
				di->forthismap = false; // don't count the error
			}
		}
	}

	if(di->prev)
		di->prev->next = di->next;
	else
		downloads = di->next;
	if(di->next)
		di->next->prev = di->prev;

	--numdownloads;
	if(di->forthismap)
	{
		if(ok)
			++numdownloads_success;
		else
			++numdownloads_fail;
	}
	Z_Free(di);
}
예제 #13
0
파일: cl_demo.c 프로젝트: DrBeef/QuakeGVR
/*
====================
CL_Record_f

record <demoname> <map> [cd track]
====================
*/
void CL_Record_f (void)
{
    int c, track;
    char name[MAX_OSPATH];
    char vabuf[1024];

    c = Cmd_Argc();
    if (c != 2 && c != 3 && c != 4)
    {
        Con_Print("record <demoname> [<map> [cd track]]\n");
        return;
    }

    if (strstr(Cmd_Argv(1), ".."))
    {
        Con_Print("Relative pathnames are not allowed.\n");
        return;
    }

    if (c == 2 && cls.state == ca_connected)
    {
        Con_Print("Can not record - already connected to server\nClient demo recording must be started before connecting\n");
        return;
    }

    if (cls.state == ca_connected)
        CL_Disconnect();

    // write the forced cd track number, or -1
    if (c == 4)
    {
        track = atoi(Cmd_Argv(3));
        Con_Printf("Forcing CD track to %i\n", cls.forcetrack);
    }
    else
        track = -1;

    // get the demo name
    strlcpy (name, Cmd_Argv(1), sizeof (name));
    FS_DefaultExtension (name, ".dem", sizeof (name));

    // start the map up
    if (c > 2)
        Cmd_ExecuteString ( va(vabuf, sizeof(vabuf), "map %s", Cmd_Argv(2)), src_command, false);

    // open the demo file
    Con_Printf("recording to %s.\n", name);
    cls.demofile = FS_OpenRealFile(name, "wb", false);
    if (!cls.demofile)
    {
        Con_Print("ERROR: couldn't open.\n");
        return;
    }
    strlcpy(cls.demoname, name, sizeof(cls.demoname));

    cls.forcetrack = track;
    FS_Printf(cls.demofile, "%i\n", cls.forcetrack);

    cls.demorecording = true;
    cls.demo_lastcsprogssize = -1;
    cls.demo_lastcsprogscrc = -1;
}
예제 #14
0
static void Curl_EndDownload(downloadinfo *di, CurlStatus status, CURLcode error, const char *content_type_)
{
	char content_type[64];
	qboolean ok = false;
	if(!curl_dll)
		return;
	switch(status)
	{
		case CURL_DOWNLOAD_SUCCESS:
			ok = true;
			di->callback(CURLCBSTATUS_OK, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_FAILED:
			di->callback(CURLCBSTATUS_FAILED, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_ABORTED:
			di->callback(CURLCBSTATUS_ABORTED, di->bytes_received, di->buffer, di->callback_data);
			break;
		case CURL_DOWNLOAD_SERVERERROR:
			// reopen to enforce it to have zero bytes again
			if(di->stream)
			{
				FS_Close(di->stream);
				di->stream = FS_OpenRealFile(di->filename, "wb", false);
			}

			if(di->callback)
				di->callback(error ? (int) error : CURLCBSTATUS_SERVERERROR, di->bytes_received, di->buffer, di->callback_data);
			break;
		default:
			if(di->callback)
				di->callback(CURLCBSTATUS_UNKNOWN, di->bytes_received, di->buffer, di->callback_data);
			break;
	}
	if(content_type_)
		strlcpy(content_type, content_type_, sizeof(content_type));
	else
		*content_type = 0;

	if(di->curle)
	{
		qcurl_multi_remove_handle(curlm, di->curle);
		qcurl_easy_cleanup(di->curle);
		if(di->slist)
			qcurl_slist_free_all(di->slist);
	}

	if(!di->callback && ok && !di->bytes_received)
	{
		Con_Printf("ERROR: empty file\n");
		ok = false;
	}

	if(di->stream)
		FS_Close(di->stream);

#define CLEAR_AND_RETRY() \
	do \
	{ \
		di->stream = FS_OpenRealFile(di->filename, "wb", false); \
		FS_Close(di->stream); \
		if(di->startpos && !di->callback) \
		{ \
			Curl_Begin(di->url, di->extraheaders, di->maxspeed, di->filename, di->loadtype, di->forthismap, di->post_content_type, di->postbuf, di->postbufsize, NULL, 0, NULL, NULL); \
			di->forthismap = false; \
		} \
	} \
	while(0)

	if(ok && di->loadtype == LOADTYPE_PAK)
	{
		ok = FS_AddPack(di->filename, NULL, true);
		if(!ok)
			CLEAR_AND_RETRY();
	}
	else if(ok && di->loadtype == LOADTYPE_CACHEPIC)
	{
		const char *p;
		unsigned char *pixels = NULL;

		p = di->filename;
#ifdef WE_ARE_EVIL
		if(!strncmp(p, "dlcache/", 8))
			p += 8;
#endif

		pixels = decode_image(di, content_type);
		if(pixels)
			Draw_NewPic(p, image_width, image_height, true, pixels);
		else
			CLEAR_AND_RETRY();
	}
	else if(ok && di->loadtype == LOADTYPE_SKINFRAME)
	{
		const char *p;
		unsigned char *pixels = NULL;

		p = di->filename;
#ifdef WE_ARE_EVIL
		if(!strncmp(p, "dlcache/", 8))
			p += 8;
#endif

		pixels = decode_image(di, content_type);
		if(pixels)
			R_SkinFrame_LoadInternalBGRA(p, TEXF_FORCE_RELOAD | TEXF_MIPMAP | TEXF_ALPHA, pixels, image_width, image_height, false); // TODO what sRGB argument to put here?
		else
			CLEAR_AND_RETRY();
	}

	if(di->prev)
		di->prev->next = di->next;
	else
		downloads = di->next;
	if(di->next)
		di->next->prev = di->prev;

	--numdownloads;
	if(di->forthismap)
	{
		if(ok)
			++numdownloads_success;
		else
			++numdownloads_fail;
	}
	Z_Free(di);
}