1
0
Fork 0
forked from fte/fteqw

removed userinfobasic, things should be kept in sync more easily now.

xmpp got some major tweaks. more sasl methods etc. multiple accounts.
misc other tweaks.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4418 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2013-07-13 12:14:32 +00:00
parent 00a6409804
commit b2f5ae8f1c
28 changed files with 2625 additions and 602 deletions

View file

@ -495,7 +495,7 @@ static void UnignoreteamAll_f (void)
char Ignore_Check_Flood(char *s, int flags, int offset) char Ignore_Check_Flood(char *s, int flags, int offset)
{ {
int i, p, q, len; int i, p, q, len;
char name[MAX_INFO_STRING]; char name[MAX_INFO_KEY];
if ( !( if ( !(
( (ignore_flood.value == 1 && (flags & TPM_NORMAL || flags & TPM_SPECTATOR)) || ( (ignore_flood.value == 1 && (flags & TPM_NORMAL || flags & TPM_SPECTATOR)) ||
@ -523,7 +523,7 @@ char Ignore_Check_Flood(char *s, int flags, int offset)
else else
return NO_IGNORE_NO_ADD; return NO_IGNORE_NO_ADD;
len = bound (0, q - p + 1, MAX_INFO_STRING - 1); len = bound (0, q - p + 1, sizeof(name) - 1);
Q_strncpyz(name, s + p, len + 1); Q_strncpyz(name, s + p, len + 1);
if (!cls.demoplayback && !strcmp(name, Player_MyName())) if (!cls.demoplayback && !strcmp(name, Player_MyName()))

View file

@ -47,7 +47,7 @@ cvar_t cl_timeout = SCVAR("cl_timeout", "60");
cvar_t cl_shownet = CVARD("cl_shownet","0", "Debugging var. 0 shows nothing. 1 shows incoming packet sizes. 2 shows individual messages. 3 shows entities too."); // can be 0, 1, or 2 cvar_t cl_shownet = CVARD("cl_shownet","0", "Debugging var. 0 shows nothing. 1 shows incoming packet sizes. 2 shows individual messages. 3 shows entities too."); // can be 0, 1, or 2
cvar_t cl_pure = CVARD("cl_pure", "0", "If enabled, the filesystem will be restricted to allow only the content of the current server."); cvar_t cl_pure = CVARD("cl_pure", "0", "0=standard quake rules.\n1=clients should prefer files within packages present on the server.\n2=clients should use *only* files within packages present on the server.\nDue to quake 1.01/1.06 differences, a setting of 2 is only reliable with total conversions.\nIf sv_pure is set, the client will prefer the highest value set.");
cvar_t cl_sbar = CVARFC("cl_sbar", "0", CVAR_ARCHIVE, CL_Sbar_Callback); cvar_t cl_sbar = CVARFC("cl_sbar", "0", CVAR_ARCHIVE, CL_Sbar_Callback);
cvar_t cl_hudswap = CVARF("cl_hudswap", "0", CVAR_ARCHIVE); cvar_t cl_hudswap = CVARF("cl_hudswap", "0", CVAR_ARCHIVE);
cvar_t cl_maxfps = CVARF("cl_maxfps", "500", CVAR_ARCHIVE); cvar_t cl_maxfps = CVARF("cl_maxfps", "500", CVAR_ARCHIVE);
@ -1530,7 +1530,7 @@ void CL_PakDownloads(int mode)
void CL_CheckServerPacks(void) void CL_CheckServerPacks(void)
{ {
static int oldpure; static int oldpure;
int pure = atof(Info_ValueForKey(cl.serverinfo, "sv_pure"))*2; int pure = atof(Info_ValueForKey(cl.serverinfo, "sv_pure"));
if (pure < cl_pure.ival) if (pure < cl_pure.ival)
pure = cl_pure.ival; pure = cl_pure.ival;
pure = bound(0, pure, 2); pure = bound(0, pure, 2);
@ -4044,6 +4044,9 @@ double Host_Frame (double time)
maxfps = 4; maxfps = 4;
} }
if (vid.isminimized && maxfps <= 0 || maxfps > 10)
maxfps = 10;
if (maxfps > 0 if (maxfps > 0
#if !defined(NOMEDIA) #if !defined(NOMEDIA)
&& Media_Capturing() != 2 && Media_Capturing() != 2
@ -4053,7 +4056,7 @@ double Host_Frame (double time)
realtime += spare/1000; //don't use it all! realtime += spare/1000; //don't use it all!
spare = CL_FilterTime((realtime - oldrealtime)*1000, maxfps, maxfpsignoreserver); spare = CL_FilterTime((realtime - oldrealtime)*1000, maxfps, maxfpsignoreserver);
if (!spare) if (!spare)
return cl_yieldcpu.ival ? (1.0 / maxfps - (realtime - oldrealtime)) : 0; return (cl_yieldcpu.ival || vid.isminimized)? (1.0 / maxfps - (realtime - oldrealtime)) : 0;
if (spare < 0 || cls.state < ca_onserver) if (spare < 0 || cls.state < ca_onserver)
spare = 0; //uncapped. spare = 0; //uncapped.
if (spare > cl_sparemsec.ival) if (spare > cl_sparemsec.ival)
@ -4150,7 +4153,7 @@ double Host_Frame (double time)
if (host_speeds.ival) if (host_speeds.ival)
time1 = Sys_DoubleTime (); time1 = Sys_DoubleTime ();
if (SCR_UpdateScreen) if (SCR_UpdateScreen && !vid.isminimized)
{ {
extern mleaf_t *r_viewleaf; extern mleaf_t *r_viewleaf;
extern cvar_t scr_chatmodecvar; extern cvar_t scr_chatmodecvar;

View file

@ -3351,9 +3351,9 @@ void CLQ2_ParseClientinfo(int i, char *s)
Info_SetValueForKey(player->userinfo, "model", model, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "model", model, MAX_INFO_STRING);
Info_SetValueForKey(player->userinfo, "skin", skin, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "skin", skin, MAX_INFO_STRING);
#else #else
Info_SetValueForKey(player->userinfo, "skin", model, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "skin", model, sizeof(player->userinfo));
#endif #endif
Info_SetValueForKey(player->userinfo, "name", name, MAX_INFO_STRING); Info_SetValueForKey(player->userinfo, "name", name, sizeof(player->userinfo));
cl.players[i].userid = i; cl.players[i].userid = i;
cl.players[i].rbottomcolor = 1; cl.players[i].rbottomcolor = 1;

View file

@ -403,7 +403,14 @@ qintptr_t VARGS Plug_Con_SubPrint(void *offset, quintptr_t mask, const qintptr_t
name = ""; name = "";
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
{
if (!*name)
{
Con_Printf("%s", text);
return 1;
}
return false; return false;
}
con = Con_FindConsole(name); con = Con_FindConsole(name);
if (!con) if (!con)

View file

@ -661,6 +661,12 @@ void Key_DefaultLinkClicked(char *text, char *info)
Cbuf_AddText(va("\njoin %s\n", c), RESTRICT_LOCAL); Cbuf_AddText(va("\njoin %s\n", c), RESTRICT_LOCAL);
return; return;
} }
/*c = Info_ValueForKey(info, "url");
if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{
Cbuf_AddText(va("\nplayfilm %s\n", c), RESTRICT_LOCAL);
return;
}*/
c = Info_ValueForKey(info, "observe"); c = Info_ValueForKey(info, "observe");
if (*c && !strchr(c, ';') && !strchr(c, '\n')) if (*c && !strchr(c, ';') && !strchr(c, '\n'))
{ {

View file

@ -2193,7 +2193,7 @@ struct pendingfilms_s
qboolean Media_BeginNextFilm(void) qboolean Media_BeginNextFilm(void)
{ {
cin_t *cin; cin_t *cin;
static char sname[MAX_QPATH]; char sname[MAX_QPATH];
struct pendingfilms_s *p; struct pendingfilms_s *p;
if (!pendingfilms) if (!pendingfilms)
@ -2201,12 +2201,15 @@ qboolean Media_BeginNextFilm(void)
p = pendingfilms; p = pendingfilms;
pendingfilms = p->next; pendingfilms = p->next;
snprintf(sname, sizeof(sname), "cinematic/%s", p->name); snprintf(sname, sizeof(sname), "cinematic/%s", p->name);
Z_Free(p);
if (!qrenderer) if (!qrenderer)
{
Z_Free(p);
return false; return false;
}
videoshader = R_RegisterCustom(sname, Shader_DefaultCinematic, sname+10); videoshader = R_RegisterCustom(sname, Shader_DefaultCinematic, p->name);
Z_Free(p);
cin = R_ShaderGetCinematic(videoshader); cin = R_ShaderGetCinematic(videoshader);
if (cin) if (cin)

View file

@ -445,6 +445,7 @@ extern cvar_t r_editlights_import_specular;
extern cvar_t r_mirroralpha; extern cvar_t r_mirroralpha;
extern cvar_t r_wateralpha; extern cvar_t r_wateralpha;
extern cvar_t r_waterstyle; extern cvar_t r_waterstyle;
extern cvar_t r_slimestyle;
extern cvar_t r_lavastyle; extern cvar_t r_lavastyle;
extern cvar_t r_dynamic; extern cvar_t r_dynamic;
extern cvar_t r_novis; extern cvar_t r_novis;

View file

@ -364,8 +364,9 @@ cvar_t r_editlights_import_specular = SCVAR ("r_editlights_import_specular", "
cvar_t r_shadow_shadowmapping = SCVARF ("debug_r_shadow_shadowmapping", "0", 0); cvar_t r_shadow_shadowmapping = SCVARF ("debug_r_shadow_shadowmapping", "0", 0);
cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8"); cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8");
cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE); cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE);
cvar_t r_waterstyle = CVARFD ("r_waterstyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes how water, slime, and teleporters are drawn. Possible values are:\n0: fastturb-style block colour.\n1: regular q1-style water.\n2: refraction(ripply and transparent)\n3: refraction with reflection at an angle\n4: ripplemapped without reflections (requires particle effects)\n5: ripples+reflections"); cvar_t r_waterstyle = CVARFD ("r_waterstyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes how water, and teleporters are drawn. Possible values are:\n0: fastturb-style block colour.\n1: regular q1-style water.\n2: refraction(ripply and transparent)\n3: refraction with reflection at an angle\n4: ripplemapped without reflections (requires particle effects)\n5: ripples+reflections");
cvar_t r_lavastyle = CVARFD ("r_lavastyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only lava."); cvar_t r_slimestyle = CVARFD ("r_slimestyle", "", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only slime. If empty, defers to r_waterstyle.");
cvar_t r_lavastyle = CVARFD ("r_lavastyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only lava. If empty, defers to r_waterstyle.");
cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0"); cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0");
@ -1058,7 +1059,7 @@ qboolean R_ApplyRenderer (rendererstate_t *newr)
if (qrenderer == QR_NONE) if (qrenderer == QR_NONE)
{ {
if (newr->renderer->rtype == qrenderer) if (newr->renderer->rtype == qrenderer && currentrendererstate.renderer)
return true; //no point return true; //no point
Sys_CloseTerminal (); Sys_CloseTerminal ();

View file

@ -50,6 +50,7 @@ typedef struct vrect_s
typedef struct typedef struct
{ {
qboolean isminimized; //can omit rendering as it won't be seen anyway.
int fullbright; // index of first fullbright color int fullbright; // index of first fullbright color
unsigned width; /*virtual 2d width*/ unsigned width; /*virtual 2d width*/

View file

@ -2906,6 +2906,48 @@ conchar_t *COM_ParseFunString(conchar_t defaultflags, const char *str, conchar_t
} }
continue; continue;
} }
/*
else if ((str[0] == 'h' && str[1] == 't' && str[2] == 't' && str[3] == 'p' && str[4] == ':' && !linkstart && !(flags & (PFS_NOMARKUP|PFS_KEEPMARKUP))) ||
(str[0] == 'h' && str[1] == 't' && str[2] == 't' && str[3] == 'p' && str[4] == 's' && str[5] == ':' && !linkstart && !(flags & (PFS_NOMARKUP|PFS_KEEPMARKUP))))
{
//this code can just recurse. saves affecting the rest of the code with weird encodings.
int l;
char temp[1024];
conchar_t *ls, *le;
l = 0;
while (*str && l < sizeof(temp)-32 && (
(*str >= 'a' && *str <= 'z') ||
(*str >= 'A' && *str <= 'Z') ||
(*str >= '0' && *str <= '9') ||
*str == '.' || *str == '/' || *str == '&' || *str == '=' || *str == '_' || *str == '%' || *str == '?' || *str == ':'))
l += utf8_encode(temp+l, *str++, sizeof(temp)-1);
//recurse
temp[l] = 0;
if (!--outsize)
break;
*out++ = CON_LINKSTART;
ls = out;
l = COM_ParseFunString(COLOR_BLUE << CON_FGSHIFT, temp, out, outsize, PFS_FORCEUTF8|PFS_NOMARKUP) - out;
outsize -= l;
out += l;
le = out;
*out++ = '\\' | CON_HIDDEN;
*out++ = 'u' | CON_HIDDEN;
*out++ = 'r' | CON_HIDDEN;
*out++ = 'l' | CON_HIDDEN;
*out++ = '\\' | CON_HIDDEN;
while (ls < le)
*out++ = (*ls++ & CON_CHARMASK) | CON_HIDDEN;
*out++ = CON_LINKEND;
if (!--outsize)
break;
*out++ = CON_LINKEND;
continue;
}
*/
messedup: messedup:
if (!--outsize) if (!--outsize)
break; break;

View file

@ -47,7 +47,7 @@ typedef enum {false, true} qboolean;
#define STRINGIFY2(s) #s #define STRINGIFY2(s) #s
#define STRINGIFY(s) STRINGIFY2(s) #define STRINGIFY(s) STRINGIFY2(s)
#define MAX_INFO_STRING 196 //regular quakeworld. Sickening isn't it. #define BASIC_INFO_STRING 196 //regular quakeworld. Sickening isn't it.
#define EXTENDED_INFO_STRING 1024 #define EXTENDED_INFO_STRING 1024
#define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here. #define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here.
#define MAX_LOCALINFO_STRING 32768 #define MAX_LOCALINFO_STRING 32768
@ -511,7 +511,7 @@ qbyte COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence); qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence);
int SHA1(char *digest, int maxdigestsize, char *string, int stringlen); int SHA1(char *digest, int maxdigestsize, char *string, int stringlen);
int SHA1_HMAC(unsigned char *digest, int maxdigestsize, unsigned char *key, int keylen, unsigned char *data, int datalen); int SHA1_HMAC(unsigned char *digest, int maxdigestsize, unsigned char *data, int datalen, unsigned char *key, int keylen);
int version_number(void); int version_number(void);
char *version_string(void); char *version_string(void);

View file

@ -27,6 +27,7 @@ static struct
BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*); BOOL (WINAPI *pCertGetCertificateChain) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,PCCERT_CHAIN_CONTEXT*);
BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS); BOOL (WINAPI *pCertVerifyCertificateChainPolicy) (LPCSTR,PCCERT_CHAIN_CONTEXT,PCERT_CHAIN_POLICY_PARA,PCERT_CHAIN_POLICY_STATUS);
void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT); void (WINAPI *pCertFreeCertificateChain) (PCCERT_CHAIN_CONTEXT);
DWORD (WINAPI *pCertNameToStrA) (DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, DWORD dwStrType, LPTSTR psz, DWORD csz);
} crypt; } crypt;
static qboolean SSL_Init(void) static qboolean SSL_Init(void)
{ {
@ -48,6 +49,7 @@ static qboolean SSL_Init(void)
{(void**)&crypt.pCertGetCertificateChain, "CertGetCertificateChain"}, {(void**)&crypt.pCertGetCertificateChain, "CertGetCertificateChain"},
{(void**)&crypt.pCertVerifyCertificateChainPolicy, "CertVerifyCertificateChainPolicy"}, {(void**)&crypt.pCertVerifyCertificateChainPolicy, "CertVerifyCertificateChainPolicy"},
{(void**)&crypt.pCertFreeCertificateChain, "CertFreeCertificateChain"}, {(void**)&crypt.pCertFreeCertificateChain, "CertFreeCertificateChain"},
{(void**)&crypt.pCertNameToStrA, "CertNameToStrA"},
{NULL, NULL} {NULL, NULL}
}; };
@ -337,6 +339,7 @@ static DWORD VerifyServerCertificate(PCCERT_CONTEXT pServerCert, PWSTR pwszServe
{ {
if (PolicyStatus.dwError) if (PolicyStatus.dwError)
{ {
char fmsg[512];
char *err; char *err;
Status = PolicyStatus.dwError; Status = PolicyStatus.dwError;
switch (Status) switch (Status)
@ -355,7 +358,11 @@ static DWORD VerifyServerCertificate(PCCERT_CONTEXT pServerCert, PWSTR pwszServe
case CERT_E_REVOKED: err = "CERT_E_REVOKED"; break; case CERT_E_REVOKED: err = "CERT_E_REVOKED"; break;
case CERT_E_UNTRUSTEDTESTROOT: err = "CERT_E_UNTRUSTEDTESTROOT"; break; case CERT_E_UNTRUSTEDTESTROOT: err = "CERT_E_UNTRUSTEDTESTROOT"; break;
case CERT_E_REVOCATION_FAILURE: err = "CERT_E_REVOCATION_FAILURE"; break; case CERT_E_REVOCATION_FAILURE: err = "CERT_E_REVOCATION_FAILURE"; break;
case CERT_E_CN_NO_MATCH: err = "CERT_E_CN_NO_MATCH"; break; case CERT_E_CN_NO_MATCH:
err = fmsg;
Q_strncpyz(fmsg, "Certificate is for ", sizeof(fmsg));
crypt.pCertNameToStrA(X509_ASN_ENCODING, &pServerCert->pCertInfo->Subject, 0, fmsg+strlen(fmsg), sizeof(fmsg)-strlen(fmsg));
break;
case CERT_E_WRONG_USAGE: err = "CERT_E_WRONG_USAGE"; break; case CERT_E_WRONG_USAGE: err = "CERT_E_WRONG_USAGE"; break;
default: err = "(unknown)"; break; default: err = "(unknown)"; break;
} }

View file

@ -4817,7 +4817,10 @@ qboolean NET_Sleep(int msec, qboolean stdinissocket)
timeout.tv_sec = msec/1000; timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000; timeout.tv_usec = (msec%1000)*1000;
select(maxfd+1, &fdset, NULL, NULL, &timeout); if (!maxfd)
Sys_Sleep(msec/1000.0);
else
select(maxfd+1, &fdset, NULL, NULL, &timeout);
if (stdinissocket) if (stdinissocket)
return FD_ISSET(0, &fdset); return FD_ISSET(0, &fdset);
@ -5303,7 +5306,7 @@ static qboolean ICE_SendSpam(struct icestate_s *con)
data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute data[2] = ((buf.cursize+4+sizeof(integ)-20)>>8)&0xff; //hashed header length is up to the end of the hmac attribute
data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff; data[3] = ((buf.cursize+4+sizeof(integ)-20)>>0)&0xff;
//but the hash is to the start of the attribute's header //but the hash is to the start of the attribute's header
SHA1_HMAC(integ, sizeof(integ), con->rpwd, strlen(con->rpwd), data, buf.cursize); SHA1_HMAC(integ, sizeof(integ), data, buf.cursize, con->rpwd, strlen(con->rpwd));
MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY MSG_WriteShort(&buf, BigShort(0x8)); //MESSAGE-INTEGRITY
MSG_WriteShort(&buf, BigShort(20)); //sha1 key length MSG_WriteShort(&buf, BigShort(20)); //sha1 key length
SZ_Write(&buf, integ, sizeof(integ)); //integrity data SZ_Write(&buf, integ, sizeof(integ)); //integrity data
@ -5521,6 +5524,13 @@ void QDECL ICE_AddRCandidateInfo(struct icestate_s *con, struct icecandinfo_s *n
if (!NET_StringToAdr(n->addr, n->port, &peer)) if (!NET_StringToAdr(n->addr, n->port, &peer))
return; return;
if (peer.type == NA_IP)
{
//ignore invalid addresses
if (!peer.address.ip[0] && !peer.address.ip[1] && !peer.address.ip[2] && !peer.address.ip[3])
return;
}
for (o = con->rc; o; o = o->next) for (o = con->rc; o; o = o->next)
{ {
//not sure that updating candidates is particuarly useful tbh, but hey. //not sure that updating candidates is particuarly useful tbh, but hey.
@ -5909,7 +5919,7 @@ static qboolean NET_WasStun(netsrc_t netsrc)
char key[20]; char key[20];
//the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header. //the hmac is a bit weird. the header length includes the integrity attribute's length, but the checksum doesn't even consider the attribute header.
stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun)); stun->msglen = BigShort(integritypos+sizeof(integrity) - (char*)stun - sizeof(*stun));
SHA1_HMAC(key, sizeof(key), con->lpwd, strlen(con->lpwd), (qbyte*)stun, integritypos-4 - (char*)stun); SHA1_HMAC(key, sizeof(key), (qbyte*)stun, integritypos-4 - (char*)stun, con->lpwd, strlen(con->lpwd));
if (memcmp(key, integrity, sizeof(integrity))) if (memcmp(key, integrity, sizeof(integrity)))
{ {
Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity); Con_DPrintf("Integrity is bad! needed %x got %x\n", *(int*)key, *(int*)integrity);

View file

@ -1613,13 +1613,18 @@ void Plug_Close(plugin_t *plug)
} }
Con_Printf("Closing plugin %s\n", plug->name); Con_Printf("Closing plugin %s\n", plug->name);
if (plug->shutdown)
{
plugin_t *cp = currentplug;
currentplug = plug;
VM_Call(plug->vm, plug->shutdown);
currentplug = cp;
}
#if defined(PLUGINS) && !defined(NOMEDIA) && !defined(SERVERONLY) #if defined(PLUGINS) && !defined(NOMEDIA) && !defined(SERVERONLY)
Media_UnregisterDecoder(plug, NULL); Media_UnregisterDecoder(plug, NULL);
Media_UnregisterEncoder(plug, NULL); Media_UnregisterEncoder(plug, NULL);
#endif #endif
FS_UnRegisterFileSystemModule(plug); FS_UnRegisterFileSystemModule(plug);
if (plug->shutdown)
VM_Call(plug->vm, plug->shutdown);
VM_Destroy(plug->vm); VM_Destroy(plug->vm);
for (i = 0; i < pluginstreamarraylen; i++) for (i = 0; i < pluginstreamarraylen; i++)

View file

@ -15,7 +15,7 @@ This file came to FTE via EzQuake.
*/ */
/* #define SHA1HANDSOFF * Copies data before messing with it. */ /* #define SHA1HANDSOFF * Copies data before messing with it. */
#define SHA1HANDSOFF
//#include "quakedef.h" //#include "quakedef.h"
#include <string.h> #include <string.h>
@ -226,19 +226,19 @@ static void memxor(char *dest, char *src, size_t length)
} }
int SHA1_HMAC(unsigned char *digest, int maxdigestsize, int SHA1_HMAC(unsigned char *digest, int maxdigestsize,
unsigned char *key, int keylen, unsigned char *data, int datalen,
unsigned char *data, int datalen) unsigned char *key, int keylen)
{ {
SHA1_CTX inner; SHA1_CTX inner;
SHA1_CTX outer; SHA1_CTX outer;
char optkeybuf[20]; char optkeybuf[DIGEST_SIZE];
char block[64]; char block[64];
char innerhash[20]; char innerhash[DIGEST_SIZE];
if (maxdigestsize < DIGEST_SIZE) if (maxdigestsize < DIGEST_SIZE)
return 0; return 0;
/* Reduce the key's size, so that it becomes <= 64 bytes large. */ /* Reduce the key's size, so that it is never larger than a block. */
if (keylen > 64) if (keylen > 64)
{ {
@ -249,7 +249,7 @@ int SHA1_HMAC(unsigned char *digest, int maxdigestsize,
SHA1Final (optkeybuf, &keyhash); SHA1Final (optkeybuf, &keyhash);
key = optkeybuf; key = optkeybuf;
keylen = 20; keylen = sizeof(optkeybuf);
} }
/* Compute INNERHASH from KEY and IN. */ /* Compute INNERHASH from KEY and IN. */

View file

@ -4259,8 +4259,10 @@ char *Shader_DefaultBSPWater(char *shortname)
else if (r_fastturb.ival) else if (r_fastturb.ival)
wstyle = 0; wstyle = 0;
#ifdef GLQUAKE #ifdef GLQUAKE
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && !strncmp(shortname, "*lava", 5)) else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && !strncmp(shortname, "*lava", 5) && *r_lavastyle.string)
wstyle = r_lavastyle.ival; wstyle = r_lavastyle.ival;
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && !strncmp(shortname, "*slime", 5) && *r_lavastyle.string)
wstyle = r_slimestyle.ival;
else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && strncmp(shortname, "*lava", 5)) else if (qrenderer == QR_OPENGL && gl_config.arb_shader_objects && strncmp(shortname, "*lava", 5))
wstyle = r_waterstyle.ival<1?1:r_waterstyle.ival; wstyle = r_waterstyle.ival<1?1:r_waterstyle.ival;
#endif #endif

View file

@ -1796,7 +1796,8 @@ qboolean GLAppActivate(BOOL fActive, BOOL minimize)
{ {
if (modestate != MS_WINDOWED) if (modestate != MS_WINDOWED)
{ {
if (vid_canalttab) { if (vid_canalttab)
{
ChangeDisplaySettings (NULL, 0); ChangeDisplaySettings (NULL, 0);
vid_wassuspended = true; vid_wassuspended = true;
} }
@ -1969,6 +1970,7 @@ LONG WINAPI GLMainWndProc (
} }
return 0; return 0;
case WM_SIZE: case WM_SIZE:
vid.isminimized = (wParam==SIZE_MINIMIZED);
if (!vid_initializing) if (!vid_initializing)
{ {
VID_UpdateWindowStatus (hWnd); VID_UpdateWindowStatus (hWnd);

View file

@ -8360,9 +8360,6 @@ void QCBUILTIN PF_ForceInfoKey(pubprogfuncs_t *prinst, struct globalvars_s *pr_g
SV_ExtractFromUserinfo (&svs.clients[e1-1], false); SV_ExtractFromUserinfo (&svs.clients[e1-1], false);
if (SV_UserInfoIsBasic(key))
Info_SetValueForKey (svs.clients[e1-1].userinfobasic, key, value, sizeof(svs.clients[e1-1].userinfobasic));
MSG_WriteByte (&sv.reliable_datagram, svc_setinfo); MSG_WriteByte (&sv.reliable_datagram, svc_setinfo);
MSG_WriteByte (&sv.reliable_datagram, e1-1); MSG_WriteByte (&sv.reliable_datagram, e1-1);
MSG_WriteString (&sv.reliable_datagram, key); MSG_WriteString (&sv.reliable_datagram, key);

View file

@ -369,7 +369,6 @@ typedef struct client_s
int challenge; int challenge;
int userid; // identifying number int userid; // identifying number
char userinfobasic[MAX_INFO_STRING];
char userinfo[EXTENDED_INFO_STRING]; // infostring char userinfo[EXTENDED_INFO_STRING]; // infostring
usercmd_t lastcmd; // for filling in big drops and partial predictions usercmd_t lastcmd; // for filling in big drops and partial predictions
@ -944,6 +943,7 @@ void SV_ExecInitialConfigs(char *defaultexec);
int SV_CalcPing (client_t *cl, qboolean forcecalc); int SV_CalcPing (client_t *cl, qboolean forcecalc);
void SV_FullClientUpdate (client_t *client, client_t *to); void SV_FullClientUpdate (client_t *client, client_t *to);
void SV_GeneratePublicUserInfo(int pext, client_t *cl, char *info, int infolength);
int SV_ModelIndex (char *name); int SV_ModelIndex (char *name);

View file

@ -1130,7 +1130,7 @@ void SV_ForceName_f (void)
while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum))) while((cl = SV_GetClientForString(Cmd_Argv(1), &clnum)))
{ {
Info_SetValueForKey(cl->userinfo, "name", Cmd_Argv(2), MAX_INFO_STRING); Info_SetValueForKey(cl->userinfo, "name", Cmd_Argv(2), EXTENDED_INFO_STRING);
SV_LogPlayer(cl, "name forced"); SV_LogPlayer(cl, "name forced");
SV_ExtractFromUserinfo(cl, true); SV_ExtractFromUserinfo(cl, true);
Q_strncpyz(cl->name, Cmd_Argv(2), sizeof(cl->namebuf)); Q_strncpyz(cl->name, Cmd_Argv(2), sizeof(cl->namebuf));

View file

@ -599,7 +599,6 @@ void SV_DropClient (client_t *drop)
drop->namebuf[0] = 0; drop->namebuf[0] = 0;
drop->name = drop->namebuf; drop->name = drop->namebuf;
memset (drop->userinfo, 0, sizeof(drop->userinfo)); memset (drop->userinfo, 0, sizeof(drop->userinfo));
memset (drop->userinfobasic, 0, sizeof(drop->userinfobasic));
while ((lp = drop->laggedpacket)) while ((lp = drop->laggedpacket))
{ {
@ -876,20 +875,36 @@ int SV_CalcPing (client_t *cl, qboolean forcecalc)
return 0; return 0;
} }
void SV_GenerateBasicUserInfo(client_t *cl) //generate whatever public userinfo is supported by the client.
//private keys like _ prefixes and the password key are stripped out here.
//password needs to be stripped in case the password key doesn't actually relate to this server.
void SV_GeneratePublicUserInfo(int pext, client_t *cl, char *info, int infolength)
{ {
char *key, *s; char *key, *s;
int i; int i;
for (i= 1; (key = Info_KeyForNumber(cl->userinfo, i)); i++)
//FIXME: we should probably use some sort of priority system instead if I'm honest about it
if (pext & PEXT_BIGUSERINFOS)
Q_strncpyz (info, cl->userinfo, sizeof(info));
else
{ {
if (!*key) if (infolength >= BASIC_INFO_STRING)
break; infolength = BASIC_INFO_STRING;
if (!SV_UserInfoIsBasic(key)) for (i = 0; (key = Info_KeyForNumber(cl->userinfo, i)); i++)
continue; {
if (!*key)
break;
if (!SV_UserInfoIsBasic(key))
continue;
s = Info_ValueForKey(cl->userinfo, key); s = Info_ValueForKey(cl->userinfo, key);
Info_SetValueForStarKey (cl->userinfobasic, key, s, sizeof(cl->userinfobasic)); Info_SetValueForStarKey (info, key, s, infolength);
}
} }
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
Info_RemoveKey(info, "password");
Info_RemoveKey(info, "*ip");
} }
/* /*
@ -902,7 +917,7 @@ Writes all update values to client. use to=NULL to broadcast.
void SV_FullClientUpdate (client_t *client, client_t *to) void SV_FullClientUpdate (client_t *client, client_t *to)
{ {
int i; int i;
char info[MAX_INFO_STRING]; char info[EXTENDED_INFO_STRING];
if (!to) if (!to)
{ {
@ -910,6 +925,8 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
{ {
SV_FullClientUpdate(client, &svs.clients[i]); SV_FullClientUpdate(client, &svs.clients[i]);
} }
if (sv.mvdrecording)
SV_FullClientUpdate(client, &demo.recorder);
return; return;
} }
@ -941,12 +958,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
ClientReliableWrite_Byte (to, i); ClientReliableWrite_Byte (to, i);
ClientReliableWrite_Float (to, realtime - client->connection_started); ClientReliableWrite_Float (to, realtime - client->connection_started);
if ((to->fteprotocolextensions) & PEXT_BIGUSERINFOS) SV_GeneratePublicUserInfo(to->fteprotocolextensions, client, info, sizeof(info));
Q_strncpyz (info, client->userinfo, sizeof(info));
else
Q_strncpyz (info, client->userinfobasic, sizeof(info));
Info_RemoveKey(info, "password"); //main password key
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info)); ClientReliableWrite_Begin(to, svc_updateuserinfo, 7 + strlen(info));
ClientReliableWrite_Byte (to, i); ClientReliableWrite_Byte (to, i);
@ -2464,7 +2476,6 @@ client_t *SVC_DirectConnect(void)
// parse some info from the info strings // parse some info from the info strings
SV_ExtractFromUserinfo (newcl, true); SV_ExtractFromUserinfo (newcl, true);
SV_GenerateBasicUserInfo (newcl);
// JACK: Init the floodprot stuff. // JACK: Init the floodprot stuff.
newcl->floodprotmessage = 0.0; newcl->floodprotmessage = 0.0;
@ -4030,6 +4041,11 @@ void SV_MVDStream_Poll(void);
SV_MVDStream_Poll(); SV_MVDStream_Poll();
} }
#ifdef PLUGINS
if (isDedicated)
Plug_Tick();
#endif
if (sv.state < ss_active || !sv.world.worldmodel) if (sv.state < ss_active || !sv.world.worldmodel)
{ {
#ifndef SERVERONLY #ifndef SERVERONLY
@ -4117,9 +4133,6 @@ void SV_MVDStream_Poll(void);
if (isDedicated) if (isDedicated)
#endif #endif
{ {
#ifdef PLUGINS
Plug_Tick();
#endif
NET_Tick(); NET_Tick();
SV_GetConsoleCommands (); SV_GetConsoleCommands ();

View file

@ -773,7 +773,7 @@ void SV_MVDPings (void)
} }
void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player) void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
{ {
char info[MAX_INFO_STRING]; char info[EXTENDED_INFO_STRING];
qboolean dosizes; qboolean dosizes;
if (!sv.mvdrecording) if (!sv.mvdrecording)
@ -805,10 +805,7 @@ void SV_MVD_FullClientUpdate(sizebuf_t *msg, client_t *player)
MSG_WriteByte (msg, player - svs.clients); MSG_WriteByte (msg, player - svs.clients);
MSG_WriteFloat (msg, realtime - player->connection_started); MSG_WriteFloat (msg, realtime - player->connection_started);
Q_strncpyz (info, player->userinfo, MAX_INFO_STRING); SV_GeneratePublicUserInfo(demo.recorder.fteprotocolextensions, player, info, sizeof(info));
Info_RemovePrefixedKeys (info, '_'); // server passwords, etc
Info_RemoveKey(info, "password");
Info_RemoveKey(info, "*ip");
if (dosizes) if (dosizes)
msg = MVDWrite_Begin (dem_all, 0, 7 + strlen(info)); msg = MVDWrite_Begin (dem_all, 0, 7 + strlen(info));

View file

@ -57,7 +57,7 @@ cvar_t sv_cmdlikercon = SCVAR("sv_cmdlikercon", "0"); //set to 1 to allow a pass
cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server. cvar_t cmd_allowaccess = SCVAR("cmd_allowaccess", "0"); //set to 1 to allow cmd to execute console commands on the server.
cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands) cvar_t cmd_gamecodelevel = SCVAR("cmd_gamecodelevel", "50"); //execution level which gamecode is told about (for unrecognised commands)
cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world."); cvar_t sv_pure = CVARFD("sv_pure", "", CVAR_SERVERINFO, "The most evil cvar in the world, many clients will ignore this.\n0=standard quake rules.\n1=clients should prefer files within packages present on the server.\n2=clients should use *only* files within packages present on the server.\nDue to quake 1.01/1.06 differences, a setting of 2 only works in total conversions.");
cvar_t sv_nqplayerphysics = CVARAD("sv_nqplayerphysics", "0", "sv_nomsec", "Disregard player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour."); cvar_t sv_nqplayerphysics = CVARAD("sv_nqplayerphysics", "0", "sv_nomsec", "Disregard player prediction and run NQ-style player physics instead. This can be used for compatibility with mods that expect exact behaviour.");
cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2", cvar_t sv_edgefriction = CVARAF("sv_edgefriction", "2",
"edgefriction", 0); "edgefriction", 0);
@ -3598,7 +3598,7 @@ Allow clients to change userinfo
void SV_SetInfo_f (void) void SV_SetInfo_f (void)
{ {
int i, j; int i, j;
char oldval[MAX_INFO_STRING]; char oldval[MAX_INFO_KEY];
char *key, *val; char *key, *val;
qboolean basic; //infos that we send to any old qw client. qboolean basic; //infos that we send to any old qw client.
client_t *client; client_t *client;
@ -3623,7 +3623,7 @@ void SV_SetInfo_f (void)
if (strstr(Cmd_Argv(1), "\\") || strstr(Cmd_Argv(2), "\\")) if (strstr(Cmd_Argv(1), "\\") || strstr(Cmd_Argv(2), "\\"))
return; // illegal char return; // illegal char
Q_strncpyz(oldval, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)), MAX_INFO_STRING); Q_strncpyz(oldval, Info_ValueForKey(host_client->userinfo, Cmd_Argv(1)), sizeof(oldval));
#ifdef VM_Q1 #ifdef VM_Q1
if (Q1QVM_UserInfoChanged(sv_player)) if (Q1QVM_UserInfoChanged(sv_player))
@ -3656,8 +3656,6 @@ void SV_SetInfo_f (void)
basic = SV_UserInfoIsBasic(key); basic = SV_UserInfoIsBasic(key);
if (basic)
Info_SetValueForKey (host_client->userinfobasic, key, val, sizeof(host_client->userinfobasic));
for (j = 0; j < MAX_CLIENTS; j++) for (j = 0; j < MAX_CLIENTS; j++)
{ {
client = svs.clients+j; client = svs.clients+j;
@ -3690,7 +3688,7 @@ void SV_SetInfo_f (void)
} }
} }
if (sv.mvdrecording) if (sv.mvdrecording && (basic || (demo.recorder.fteprotocolextensions & PEXT_BIGUSERINFOS)))
{ {
sizebuf_t *msg = MVDWrite_Begin (dem_all, 0, strlen(key)+strlen(val)+4); sizebuf_t *msg = MVDWrite_Begin (dem_all, 0, strlen(key)+strlen(val)+4);
MSG_WriteByte (msg, svc_setinfo); MSG_WriteByte (msg, svc_setinfo);
@ -4218,7 +4216,6 @@ void Cmd_Join_f (void)
// turn the spectator into a player // turn the spectator into a player
host_client->spectator = false; host_client->spectator = false;
Info_RemoveKey (host_client->userinfo, "*spectator"); Info_RemoveKey (host_client->userinfo, "*spectator");
Info_RemoveKey (host_client->userinfobasic, "*spectator");
// FIXME, bump the client's userid? // FIXME, bump the client's userid?
@ -4328,7 +4325,6 @@ void Cmd_Observe_f (void)
// turn the player into a spectator // turn the player into a spectator
host_client->spectator = true; host_client->spectator = true;
Info_SetValueForStarKey (host_client->userinfo, "*spectator", "1", sizeof(host_client->userinfo)); Info_SetValueForStarKey (host_client->userinfo, "*spectator", "1", sizeof(host_client->userinfo));
Info_SetValueForStarKey (host_client->userinfobasic, "*spectator", "1", sizeof(host_client->userinfobasic));
// FIXME, bump the client's userid? // FIXME, bump the client's userid?

View file

@ -188,7 +188,7 @@ static void *Dec_Create(char *medianame)
medianame = medianame + 10; medianame = medianame + 10;
else if (!strcmp(medianame, "berkelium")) else if (!strcmp(medianame, "berkelium"))
medianame = (char*)"about:blank"; medianame = (char*)"about:blank";
else if (!strncmp(medianame, "http:", 5)) else if (!strncmp(medianame, "http:", 5) || !strncmp(medianame, "https:", 6))
medianame = medianame; //and direct http requests. medianame = medianame; //and direct http requests.
else else
return NULL; return NULL;
@ -304,33 +304,31 @@ static void Dec_Key (void *vctx, int code, int unicode, int isup)
} }
else else
{ {
int mods = 0;
if (code == 127)
code = 0x08;
else if (code == 140) //del
code = 0x2e;
else if (code == 143) //home
code = 0x24;
else if (code == 144) //end
code = 0x23;
else if (code == 141) //pgdn
code = 0x22;
else if (code == 142) //pgup
code = 0x21;
else if (code == 139) //ins
code = 0x2d;
else if (code == 132) //up
code = 0x26;
else if (code == 133) //down
code = 0x28;
else if (code == 134) //left
code = 0x25;
else if (code == 135) //right
code = 0x27;
if (code) if (code)
{
int mods = 0;
if (code == 127)
code = 0x08;
else if (code == 140) //del
code = 0x2e;
else if (code == 143) //home
code = 0x24;
else if (code == 144) //end
code = 0x23;
else if (code == 141) //pgdn
code = 0x22;
else if (code == 142) //pgup
code = 0x21;
else if (code == 139) //ins
code = 0x2d;
else if (code == 132) //up
code = 0x26;
else if (code == 133) //down
code = 0x28;
else if (code == 134) //left
code = 0x25;
else if (code == 135) //right
code = 0x27;
ctx->wnd->keyEvent(!isup, mods, code, 0); ctx->wnd->keyEvent(!isup, mods, code, 0);
}
if (unicode && !isup) if (unicode && !isup)
{ {
wchar_t chars[2] = {unicode}; wchar_t chars[2] = {unicode};

View file

@ -362,7 +362,50 @@ static void Decode (UINT4 *output, unsigned char *input, unsigned int len)
char *MD5_ToHex(char *input, int inputlen, char *ret, int retlen)
{
int v, i;
unsigned char digest[16];
MD5_CTX ctx;
if (retlen < 33)
return NULL;
MD5Init (&ctx);
MD5Update (&ctx, (unsigned char *)input, inputlen);
MD5Final ( (unsigned char *)digest, &ctx);
for (i = 0; i < 16; i++)
{
v = digest[i]>>4;
if (v >= 10)
ret[i*2+0] = (v-10) + 'a';
else
ret[i*2+0] = v + '0';
v = digest[i]&0xf;
if (v >= 10)
ret[i*2+1] = (v-10) + 'a';
else
ret[i*2+1] = v + '0';
}
ret[i*2] = '\0';
return ret;
}
char *MD5_ToBinary(char *input, int inputlen, char *ret, int retlen)
{
int v, i;
unsigned char digest[16];
MD5_CTX ctx;
if (retlen < 16)
return NULL;
MD5Init (&ctx);
MD5Update (&ctx, (unsigned char *)input, inputlen);
MD5Final ( (unsigned char *)ret, &ctx);
return ret;
}
char *MD5_GetPop3APOPString(char *timestamp, char *secrit) char *MD5_GetPop3APOPString(char *timestamp, char *secrit)
{ {

File diff suppressed because it is too large Load diff

View file

@ -43,6 +43,7 @@ void XML_AddParameteri(xmltree_t *t, char *paramname, int value)
} }
xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body) xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body)
{ {
int bodylen = strlen(body);
struct subtree_s *node = malloc(sizeof(*node)); struct subtree_s *node = malloc(sizeof(*node));
//clear out links //clear out links
@ -52,14 +53,26 @@ xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body
//link into parent if we actually have a parent. //link into parent if we actually have a parent.
if (parent) if (parent)
{ {
node->sibling = parent->child; if (parent->child)
parent->child = node; { //add at tail
xmltree_t *prev;
for(prev = parent->child; prev->sibling; prev = prev->sibling)
;
prev->sibling = node;
node->sibling = NULL;
}
else
{
node->sibling = parent->child;
parent->child = node;
}
} }
Q_strlcpy(node->name, name, sizeof(node->name)); Q_strlcpy(node->name, name, sizeof(node->name));
Q_strlcpy(node->xmlns, xmlns, sizeof(node->xmlns)); Q_strlcpy(node->xmlns, xmlns, sizeof(node->xmlns));
Q_strlcpy(node->xmlns_dflt, xmlns, sizeof(node->xmlns_dflt)); Q_strlcpy(node->xmlns_dflt, xmlns, sizeof(node->xmlns_dflt));
Q_strlcpy(node->body, body, sizeof(node->xmlns_dflt)); node->body = malloc(bodylen+1);
memcpy(node->body, body, bodylen+1);
if (*xmlns) if (*xmlns)
XML_AddParameter(node, "xmlns", xmlns); XML_AddParameter(node, "xmlns", xmlns);
@ -221,10 +234,10 @@ static void XML_DumpToBuf(struct buf_ctx *buf, xmltree_t *t, int indent)
buf_cat(buf, "\n", 1); buf_cat(buf, "\n", 1);
} }
char *XML_GenerateString(xmltree_t *root) char *XML_GenerateString(xmltree_t *root, qboolean readable)
{ {
struct buf_ctx buf = {NULL, 0, 0}; struct buf_ctx buf = {NULL, 0, 0};
XML_DumpToBuf(&buf, root, -1); XML_DumpToBuf(&buf, root, readable?0:-1);
buf_cat(&buf, "", 1); buf_cat(&buf, "", 1);
return buf.buf; return buf.buf;
} }
@ -234,6 +247,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
xmltree_t *child; xmltree_t *child;
xmltree_t *ret; xmltree_t *ret;
int bodypos; int bodypos;
int bodymax = 0;
int pos, i; int pos, i;
char *tagend; char *tagend;
char *tagstart; char *tagstart;
@ -283,7 +297,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
tagstart++; tagstart++;
for (i = 0; i < sizeof(token)-1 && *tagstart; ) for (i = 0; i < sizeof(token)-1 && *tagstart; )
{ {
if (*tagstart == ' ' || *tagstart == '\n' || *tagstart == '\r' || *tagstart == '\t') if (*tagstart == ' ' || (i&&*tagstart == '/') || (i&&*tagstart == '?') || *tagstart == '\n' || *tagstart == '\r' || *tagstart == '\t')
break; break;
token[i++] = *tagstart++; token[i++] = *tagstart++;
} }
@ -315,7 +329,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
int nlen; int nlen;
while(*tagstart <= ' ' && *tagstart) while(*(unsigned char*)tagstart <= ' ' && *tagstart)
tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer) tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer)
if (!*tagstart) if (!*tagstart)
@ -325,7 +339,7 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
nlen = 0; nlen = 0;
while (nlen < sizeof(p->name)-2) while (nlen < sizeof(p->name)-2)
{ {
if(*tagstart <= ' ') if (*(unsigned char*)tagstart <= ' ' || *tagstart == '/' || *tagstart == '?')
break; break;
if (*tagstart == '=') if (*tagstart == '=')
@ -334,14 +348,14 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
} }
p->name[nlen++] = '\0'; p->name[nlen++] = '\0';
while(*tagstart <= ' ' && *tagstart) while(*(unsigned char*)tagstart <= ' ' && *tagstart)
tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer) tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer)
if (*tagstart != '=') if (*tagstart != '=')
continue; break;
tagstart++; tagstart++;
while(*tagstart <= ' ' && *tagstart) while(*(unsigned char*)tagstart <= ' ' && *tagstart)
tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer) tagstart++; //skip whitespace (note that we know there is a null terminator before the end of the buffer)
nlen = 0; nlen = 0;
@ -397,6 +411,8 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
if (tagend[-2] == '/') if (tagend[-2] == '/')
{ //no body { //no body
ret->body = malloc(1);
*ret->body = 0;
*startpos = pos; *startpos = pos;
return ret; return ret;
} }
@ -405,6 +421,8 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
//no body either //no body either
if (tagend[-2] == '?') if (tagend[-2] == '?')
{ {
ret->body = malloc(1);
*ret->body = 0;
*startpos = pos; *startpos = pos;
return ret; return ret;
} }
@ -459,10 +477,27 @@ xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronl
else else
{ {
char c = buffer[pos++]; char c = buffer[pos++];
if (bodypos < sizeof(ret->body)-1) if (bodypos == bodymax)
ret->body[bodypos++] = c; {
int nlen = bodypos*2 + 64;
char *nb = malloc(nlen);
memcpy(nb, ret->body, bodypos);
free(ret->body);
ret->body = nb;
bodymax = nlen;
}
ret->body[bodypos++] = c;
} }
} }
if (bodypos == bodymax)
{
int nlen = bodypos+1;
char *nb = malloc(nlen);
memcpy(nb, ret->body, bodypos);
free(ret->body);
ret->body = nb;
bodymax = nlen;
}
ret->body[bodypos++] = '\0'; ret->body[bodypos++] = '\0';
XML_Unmark(ret->body); XML_Unmark(ret->body);
@ -486,6 +521,7 @@ void XML_Destroy(xmltree_t *t)
np = p->next; np = p->next;
free(p); free(p);
} }
free(t->body);
free(t); free(t);
} }
@ -504,6 +540,28 @@ xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum)
} }
return NULL; return NULL;
} }
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, char *xmlns, char *name, int childnum)
{
if (t)
{
for (t = t->child; t; t = t->sibling)
{
if (!strcmp(t->xmlns, xmlns) && !strcmp(t->name, name))
{
if (childnum-- == 0)
return t;
}
}
}
return NULL;
}
char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def)
{
xmltree_t *c = XML_ChildOfTree(t, paramname, 0);
if (c)
return c->body;
return def;
}
void XML_ConPrintTree(xmltree_t *t, int indent) void XML_ConPrintTree(xmltree_t *t, int indent)
{ {
@ -527,3 +585,114 @@ void XML_ConPrintTree(xmltree_t *t, int indent)
free(buf.buf); free(buf.buf);
} }
static void XML_SkipWhite(char *msg, int *pos, int max)
{
while (*pos < max && (
msg[*pos] == ' ' ||
msg[*pos] == '\t' ||
msg[*pos] == '\r' ||
msg[*pos] == '\n'
))
*pos+=1;
}
static qboolean XML_ParseString(char *msg, int *pos, int max, char *out, int outlen)
{
*out = 0;
if (*pos < max && msg[*pos] == '\"')
{
*pos+=1;
outlen--;
while (*pos < max && msg[*pos] != '\"')
{
if (!outlen)
return false;
*out = msg[*pos];
out++;
outlen--;
*pos+=1;
}
if (*pos < max && msg[*pos] == '\"')
{
*out = 0;
*pos+=1;
return true;
}
}
else
{
outlen--;
while (*pos < max
&& msg[*pos] != ' '
&& msg[*pos] != '\t'
&& msg[*pos] != '\r'
&& msg[*pos] != '\n'
&& msg[*pos] != ':'
&& msg[*pos] != ','
&& msg[*pos] != '}'
&& msg[*pos] != '{')
{
if (!outlen)
return false;
*out = msg[*pos];
out++;
outlen--;
*pos+=1;
}
*out = 0;
return true;
}
return false;
}
xmltree_t *XML_FromJSON(xmltree_t *t, char *name, char *json, int *jsonpos, int jsonlen)
{
char child[4096];
char *start;
char *end;
XML_SkipWhite(json, jsonpos, jsonlen);
if (*jsonpos < jsonlen && json[*jsonpos] == '{')
{
*jsonpos+=1;
XML_SkipWhite(json, jsonpos, jsonlen);
t = XML_CreateNode(t, name, "", "");
while (*jsonpos < jsonlen && json[*jsonpos] == '\"')
{
if (!XML_ParseString(json, jsonpos, jsonlen, child, sizeof(child)))
break;
XML_SkipWhite(json, jsonpos, jsonlen);
if (*jsonpos < jsonlen && json[*jsonpos] == ':')
{
*jsonpos+=1;
if (!XML_FromJSON(t, child, json, jsonpos, jsonlen))
break;
}
XML_SkipWhite(json, jsonpos, jsonlen);
if (*jsonpos < jsonlen && json[*jsonpos] == ',')
{
*jsonpos+=1;
XML_SkipWhite(json, jsonpos, jsonlen);
continue;
}
break;
}
if (*jsonpos < jsonlen && json[*jsonpos] == '}')
{
*jsonpos+=1;
return t;
}
XML_Destroy(t);
}
else if (*jsonpos < jsonlen)
{
if (XML_ParseString(json, jsonpos, jsonlen, child, sizeof(child)))
return XML_CreateNode(t, name, "", child);
}
return NULL;
}

View file

@ -10,7 +10,7 @@ typedef struct subtree_s
char name[64]; //FIXME: make pointer to tail of structure char name[64]; //FIXME: make pointer to tail of structure
char xmlns[64]; //namespace of the element //FIXME: make pointer to tail of structure char xmlns[64]; //namespace of the element //FIXME: make pointer to tail of structure
char xmlns_dflt[64]; //default namespace of children //FIXME: make pointer to tail of structure char xmlns_dflt[64]; //default namespace of children //FIXME: make pointer to tail of structure
char body[2048]; //FIXME: make pointer+variablesized char *body;//[2048]; //FIXME: make pointer+variablesized
xmlparams_t *params; xmlparams_t *params;
@ -26,8 +26,12 @@ void XML_AddParameteri(xmltree_t *t, char *paramname, int value);
xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body); xmltree_t *XML_CreateNode(xmltree_t *parent, char *name, char *xmlns, char *body);
char *XML_Markup(char *s, char *d, int dlen); char *XML_Markup(char *s, char *d, int dlen);
void XML_Unmark(char *s); void XML_Unmark(char *s);
char *XML_GenerateString(xmltree_t *root); char *XML_GenerateString(xmltree_t *root, qboolean readable);
xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly, char *defaultnamespace); xmltree_t *XML_Parse(char *buffer, int *startpos, int maxpos, qboolean headeronly, char *defaultnamespace);
void XML_Destroy(xmltree_t *t); void XML_Destroy(xmltree_t *t);
xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum); xmltree_t *XML_ChildOfTree(xmltree_t *t, char *name, int childnum);
xmltree_t *XML_ChildOfTreeNS(xmltree_t *t, char *xmlns, char *name, int childnum);
char *XML_GetChildBody(xmltree_t *t, char *paramname, char *def);
void XML_ConPrintTree(xmltree_t *t, int indent); void XML_ConPrintTree(xmltree_t *t, int indent);
xmltree_t *XML_FromJSON(xmltree_t *t, char *name, char *json, int *jsonpos, int jsonlen);