/* * SV_IsDemoDownloadRequest */ bool SV_IsDemoDownloadRequest( const char *request ) { const char *ext; const char *demoDir = SV_DEMO_DIR; const size_t demoDirLen = strlen( demoDir ); if( !request ) { return false; } if( strlen( request ) <= demoDirLen + 1 + strlen( APP_DEMO_EXTENSION_STR ) ) { // should at least contain demo dir name and demo file extension return false; } if( Q_strnicmp( request, demoDir, demoDirLen ) || request[demoDirLen] != '/' ) { // nah, wrong dir return false; } ext = COM_FileExtension( request ); if( !ext || !*ext || Q_stricmp( ext, APP_DEMO_EXTENSION_STR ) ) { // wrong extension return false; } return true; }
static size_t Com_MapList_m(char *buffer, size_t size) { int i, numFiles; void **list; char *s, *p; size_t len, total = 0; list = FS_ListFiles("maps", ".bsp", 0, &numFiles); for (i = 0; i < numFiles; i++) { s = list[i]; p = COM_FileExtension(list[i]); *p = 0; len = strlen(s); if (total + len + 1 < size) { memcpy(buffer + total, s, len); buffer[total + len] = ' '; total += len + 1; } Z_Free(s); } buffer[total] = 0; Z_Free(list); return total; }
/* * CL_CheckOrDownloadFile * * Returns true if the file exists or couldn't send download request * Files with .pk3 or .pak extension have to have gamedir attached * Other files must not have gamedir */ qboolean CL_CheckOrDownloadFile( const char *filename ) { const char *ext; if( !cl_downloads->integer ) return qtrue; if( !COM_ValidateRelativeFilename( filename ) ) return qtrue; ext = COM_FileExtension( filename ); if( !ext || !*ext ) return qtrue; if( FS_CheckPakExtension( filename ) ) { if( FS_FOpenBaseFile( filename, NULL, FS_READ ) != -1 ) return qtrue; } else { if( FS_FOpenFile( filename, NULL, FS_READ ) != -1 ) return qtrue; } if( !CL_DownloadRequest( filename, qtrue ) ) return qtrue; cls.download.requestnext = qtrue; // call CL_RequestNextDownload when done return qfalse; }
// Playlist functions void MP3_WINAMP_LoadPlaylist_f(void) { COPYDATASTRUCT cds; char playlist[64]; if (Cmd_Argc() == 1) { Com_Printf("Usage: %s <filename>\n", Cmd_Argv(0)); return; } if (!MP3_WINAMP_IsPlayerRunning()) { Com_Printf("%s is not running\n", mp3_player->PlayerName_LeadingCaps); return; } strlcpy(playlist, Cmd_Args(), sizeof(playlist)); if (!strcmp(COM_FileExtension(playlist), "pls")) { Com_Printf("Error: .pls playlists are not supported. Try loading a .m3u playlist\n"); return; } COM_ForceExtensionEx (playlist, ".m3u", sizeof (playlist)); SendMessage(mp3_hwnd, WM_WA_IPC, 0, IPC_DELETE); cds.dwData = IPC_PLAYFILE; cds.lpData = playlist; cds.cbData = strlen(playlist) + 1; SendMessage(mp3_hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) &cds); }
/* * CL_SetSoundExtension */ static char *CL_SetSoundExtension( const char *name ) { unsigned int i; char *finalname; size_t finalname_size, maxlen; const char *extension; assert( name ); if( COM_FileExtension( name ) ) return TempCopyString( name ); maxlen = 0; for( i = 0; i < NUM_SOUND_EXTENSIONS; i++ ) { if( strlen( SOUND_EXTENSIONS[i] ) > maxlen ) maxlen = strlen( SOUND_EXTENSIONS[i] ); } finalname_size = strlen( name ) + maxlen + 1; finalname = Mem_TempMalloc( finalname_size ); Q_strncpyz( finalname, name, finalname_size ); extension = FS_FirstExtension( finalname, SOUND_EXTENSIONS, NUM_SOUND_EXTENSIONS ); if( extension ) Q_strncatz( finalname, extension, finalname_size ); // if not found, we just pass it without the extension return finalname; }
/* * ML_ValidateFilename * Checks that the filename provided is valid */ bool ML_ValidateFilename( const char *filename ) { const char *extension; if( !filename || !*filename ) return false; extension = COM_FileExtension( filename ); if( !extension ) { if( strlen( "maps/" ) + strlen( filename ) + strlen( ".bsp" ) >= MAX_CONFIGSTRING_CHARS ) return false; } else { if( Q_stricmp( extension, ".bsp" ) ) return false; if( strlen( "maps/" ) + strlen( filename ) >= MAX_CONFIGSTRING_CHARS ) return false; } if( !COM_ValidateRelativeFilename( filename ) || strchr( filename, '/' ) ) return false; return true; }
static gl3image_t * LoadWal(char *origname) { miptex_t *mt; int width, height, ofs; gl3image_t *image; char name[256]; Q_strlcpy(name, origname, sizeof(name)); /* Add the extension */ if (strcmp(COM_FileExtension(name), "wal")) { Q_strlcat(name, ".wal", sizeof(name)); } ri.FS_LoadFile(name, (void **)&mt); if (!mt) { R_Printf(PRINT_ALL, "LoadWal: can't load %s\n", name); return gl3_notexture; } width = LittleLong(mt->width); height = LittleLong(mt->height); ofs = LittleLong(mt->offsets[0]); image = GL3_LoadPic(name, (byte *)mt + ofs, width, 0, height, 0, it_wall, 8); ri.FS_FreeFile((void *)mt); return image; }
/* * SV_AddPureShader * * FIXME: For now we don't parse shaders, but simply assume that it uses the same name .tga or .jpg */ static void SV_AddPureShader( const char *name ) { const char *extension; char tempname[MAX_CONFIGSTRING_CHARS]; if( !name || !name[0] ) return; assert( name && name[0] && strlen( name ) < MAX_CONFIGSTRING_CHARS ); if( !Q_strnicmp( name, "textures/common/", strlen( "textures/common/" ) ) ) return; Q_strncpyz( tempname, name, sizeof( tempname ) ); if( !COM_FileExtension( tempname ) ) { extension = FS_FirstExtension( tempname, IMAGE_EXTENSIONS, NUM_IMAGE_EXTENSIONS ); if( !extension ) return; COM_ReplaceExtension( tempname, extension, sizeof( tempname ) ); } SV_AddPureFile( tempname ); }
static void *FSGZIP_LoadGZipFile(vfsfile_t *gziphandle, const char *desc) { gzipfile_t *gzip; const char *base; char *ext; int fd; gzip = Q_calloc(1, sizeof(*gzip)); strlcpy(gzip->filename, desc, sizeof(gzip->filename)); if (gziphandle == NULL) goto fail; gzip->raw = gziphandle; fd = fileno(((vfsosfile_t *)gziphandle)->handle); // <-- ASSUMPTION! that file is OS gzip->handle = (vfsfile_t *)gzdopen(dup(fd), "r"); gzip->references = 1; /* Remove the .gz from the file.name */ base = COM_SkipPath(desc); ext = COM_FileExtension(desc); if (strcmp(ext, "gz") == 0) { COM_StripExtension(base, gzip->file.name, sizeof(gzip->file.name)); } else { strlcpy(gzip->file.name, base, sizeof(gzip->file.name)); } return gzip; fail: // Q_free is safe to call on NULL pointers Q_free(gzip); return NULL; }
//================== // SCR_RegisterFont //================== struct mufont_s *SCR_RegisterFont( const char *name ) { mufont_t *font; const char *extension; size_t len; extension = COM_FileExtension( name ); len = ( extension ? extension - name - 1 : strlen( name ) ); for( font = gs_muFonts; font; font = font->next ) { if( !Q_strnicmp( font->name, name, len ) ) return font; } font = SCR_LoadMUFont( name, len ); if( !font ) { return NULL; } font->next = gs_muFonts; gs_muFonts = font; return font; }
/* * S_StartBackgroundTrack */ void S_StartBackgroundTrack( const char *intro, const char *loop, int mode ) { const char *ext; bgTrack_t *introTrack, *loopTrack; bgTrack_t *firstTrack = NULL; S_StopBackgroundTrack(); if( !intro || !intro[0] ) { return; } s_bgTrackMuted = false; s_bgTrackPaused = false; ext = COM_FileExtension( intro ); if( ext && !Q_stricmp( ext, ".m3u" ) ) { // mode bits: // 1 - shuffle // 2 - loop the selected track // 4 - stream (even if muted) firstTrack = S_ReadPlaylistFile( intro, mode & 1 ? true : false, mode & 2 ? true : false ); if( firstTrack ) { goto start_playback; } } // the intro track loops unless another loop track has been specified introTrack = S_AllocTrack( intro ); introTrack->loop = true; introTrack->next = introTrack->prev = introTrack; introTrack->muteOnPause = introTrack->isUrl || mode & 4 ? true : false; if( loop && loop[0] && Q_stricmp( intro, loop ) ) { loopTrack = S_AllocTrack( loop ); if( S_OpenMusicTrack( loopTrack, NULL ) ) { S_CloseMusicTrack( loopTrack ); introTrack->next = introTrack->prev = loopTrack; introTrack->loop = false; loopTrack->loop = true; loopTrack->muteOnPause = loopTrack->isUrl || mode & 4 ? true : false; loopTrack->next = loopTrack->prev = loopTrack; } } firstTrack = introTrack; start_playback: if( !firstTrack || firstTrack->ignore ) { S_StopBackgroundTrack(); return; } S_OpenBackgroundTrackTask( firstTrack ); }
/* * CL_DownloadComplete * * Checks downloaded file's checksum, renames it and adds to the filesystem. */ static void CL_DownloadComplete( void ) { unsigned checksum = 0; int length; qboolean updateMapList = qfalse; FS_FCloseFile( cls.download.filenum ); cls.download.filenum = 0; // verify checksum if( FS_CheckPakExtension( cls.download.name ) ) { if( !FS_IsPakValid( cls.download.tempname, &checksum ) ) { Com_Printf( "Downloaded file is not a valid pack file. Removing\n" ); FS_RemoveBaseFile( cls.download.tempname ); return; } } else { length = FS_LoadBaseFile( cls.download.tempname, NULL, NULL, 0 ); if( length < 0 ) { Com_Printf( "Error: Couldn't load downloaded file\n" ); return; } checksum = FS_ChecksumBaseFile( cls.download.tempname ); } if( cls.download.checksum != checksum ) { Com_Printf( "Downloaded file has wrong checksum. Removing: %u %u %s\n", cls.download.checksum, checksum, cls.download.tempname ); FS_RemoveBaseFile( cls.download.tempname ); return; } if( !FS_MoveBaseFile( cls.download.tempname, cls.download.name ) ) { Com_Printf( "Failed to rename the downloaded file\n" ); return; } if( FS_CheckPakExtension( cls.download.name ) ) updateMapList = qtrue; else if( !Q_stricmp( COM_FileExtension( cls.download.name ), ".bsp" ) ) updateMapList = qtrue; // Maplist hook so we also know when a new map is added if( updateMapList ) ML_Update (); cls.download.successCount++; cls.download.timeout = 0; }
/* ================= FS_TypeFlagForPakItem Returns bit flag based on pak item's extension. ================= */ unsigned int FS_TypeFlagForPakItem(char *itemName) { int i; char *tmp, extension[8]; tmp = COM_FileExtension(itemName); strncpy(extension, tmp, sizeof(extension)); for (i = 0; type_extensions[i]; i++) { if (!Q_strcasecmp(extension, type_extensions[i])) return (1 << i); } return 0; }
/* * ML_ValidateFilename * Checks that the filename provided is valid */ qboolean ML_ValidateFilename( const char *filename ) { if( !filename || !*filename ) return qfalse; if( !COM_FileExtension( filename ) ) { if( strlen( "maps/" ) + strlen( filename ) + strlen( ".bsp" ) >= MAX_CONFIGSTRING_CHARS ) return qfalse; } else { if( Q_stricmp( COM_FileExtension( filename ), ".bsp" ) ) return qfalse; if( strlen( "maps/" ) + strlen( filename ) >= MAX_CONFIGSTRING_CHARS ) return qfalse; } if( !COM_ValidateRelativeFilename( filename ) || strchr( filename, '/' ) ) return qfalse; return qtrue; }
/* * G_AllowDownload */ qboolean G_AllowDownload( edict_t *ent, const char *requestname, const char *uploadname ) { // allow uploading of demos if( g_uploads_demos->integer ) { if( !Q_stricmp( COM_FileExtension( uploadname ), va( ".wd%i", game.protocol ) ) ) { const char *p; p = strchr( uploadname, '/' ); if( p && !Q_strnicmp( p + 1, "demos/server/", strlen( "demos/server/" ) ) ) return qtrue; } } return qfalse; }
// This should always be called with the extension removed static snd_decoder_t *findCodec( const char *filename ) { snd_decoder_t *decoder = decoders; const char *extension = COM_FileExtension( filename ); if( extension ) { while( decoder ) { if( !Q_stricmp( extension, decoder->ext ) ) return decoder; decoder = decoder->next; } } return NULL; }
/* * origname: the filename to be opened, might be without extension * type: extension of the type we wanna open ("jpg", "png" or "tga") * pic: pointer RGBA pixel data will be assigned to */ qboolean LoadSTB(const char *origname, const char* type, byte **pic, int *width, int *height) { char filename[256]; Q_strlcpy(filename, origname, sizeof(filename)); /* Add the extension */ if (strcmp(COM_FileExtension(filename), type) != 0) { Q_strlcat(filename, ".", sizeof(filename)); Q_strlcat(filename, type, sizeof(filename)); } *pic = NULL; byte* rawdata = NULL; int rawsize = FS_LoadFile(filename, (void **)&rawdata); if (rawdata == NULL) { return false; } int w, h, bytesPerPixel; byte* data = NULL; data = stbi_load_from_memory(rawdata, rawsize, &w, &h, &bytesPerPixel, STBI_rgb_alpha); if (data == NULL) { VID_Printf(PRINT_ALL, "stb_image couldn't load data from %s: %s!\n", filename, stbi_failure_reason()); FS_FreeFile(rawdata); return false; } FS_FreeFile(rawdata); VID_Printf(PRINT_DEVELOPER, "LoadSTB() loaded: %s\n", filename); *pic = data; *width = w; *height = h; return true; }
// // Find out if a given directory entry is a registered file type and // if so, returns the index of the file type. Otherwise -1 is returned. // static int FL_FindRegisteredType(filelist_t *fl, sys_dirent *ent) { int i = 0; int result = -1; if (!ent->directory) { for (i=0; i < fl->num_filetypes; i++) { char ext[_MAX_EXT]; snprintf (ext, sizeof(ext), ".%s", COM_FileExtension (ent->fname)); if (!strcasecmp(fl->filetypes[i].extension, ext)) { result = i; break; } } } return result; }
/* * PF_PureSound */ static void PF_PureSound( const char *name ) { const char *extension; char tempname[MAX_CONFIGSTRING_CHARS]; if( sv.state != ss_loading ) return; if( !name || !name[0] || strlen( name ) >= MAX_CONFIGSTRING_CHARS ) return; Q_strncpyz( tempname, name, sizeof( tempname ) ); if( !COM_FileExtension( tempname ) ) { extension = FS_FirstExtension( tempname, SOUND_EXTENSIONS, NUM_SOUND_EXTENSIONS ); if( !extension ) return; COM_ReplaceExtension( tempname, extension, sizeof( tempname ) ); } SV_AddPureFile( tempname ); }
/* <5e43> ../engine/cmd.c:347 */ void Cmd_Exec_f(void) { const char *pszFileName; const char *pszFileExt; char *pszFileData; int nAddLen; FileHandle_t hFile; if (Cmd_Argc() != 2) { Con_Printf("exec <filename> : execute a script file\n"); return; } pszFileName = Cmd_Argv(1); if (!pszFileName || pszFileName[0] == 0) { return; } if (Q_strstr(pszFileName, "\\") || Q_strstr(pszFileName, ":") || Q_strstr(pszFileName, "~") || Q_strstr(pszFileName, "..") || *pszFileName == '/') { Con_Printf("exec %s: invalid path.\n", pszFileName); return; } pszFileExt = COM_FileExtension((char *)pszFileName); if (Q_stricmp(pszFileExt, "cfg") && Q_stricmp(pszFileExt, "rc")) { Con_Printf("exec %s: not a .cfg or .rc file\n", pszFileName); return; } hFile = FS_OpenPathID(pszFileName, "rb", "GAMECONFIG"); if (!hFile) { hFile = FS_OpenPathID(pszFileName, "rb", "GAME"); } if (!hFile) { hFile = FS_Open(pszFileName, "rb"); } if (!hFile) { if (!Q_strstr(pszFileName, "autoexec.cfg") && !Q_strstr(pszFileName, "userconfig.cfg") && !Q_strstr(pszFileName, "hw/opengl.cfg") && !Q_strstr(pszFileName, "joystick.cfg") && !Q_strstr(pszFileName, "game.cfg")) { Con_Printf("couldn't exec %s\n", pszFileName); } return; } nAddLen = FS_Size(hFile); pszFileData = (char *)Mem_Malloc(nAddLen + 1); if (!pszFileData) { Con_Printf("exec: not enough space for %s", pszFileName); FS_Close(hFile); return; } FS_Read(pszFileData, nAddLen, 1, hFile); pszFileData[nAddLen] = 0; FS_Close(hFile); Con_DPrintf("execing %s\n", pszFileName); if (cmd_text.cursize + nAddLen + 2 < cmd_text.maxsize) { Cbuf_InsertTextLines(pszFileData); } else { char *pszDataPtr = pszFileData; while (true) { Cbuf_Execute(); // TODO: This doesn't obey the rule to first execute commands from the file, and then the others in the buffer pszDataPtr = COM_ParseLine(pszDataPtr); if (com_token[0] == 0) { break; } Cbuf_InsertTextLines(com_token); } } Mem_Free(pszFileData); }
/* * SV_WebDownload */ static qboolean SV_WebDownload( const char *baseUrl, const char *filepath, qboolean overwrite, qboolean silent ) { qboolean success; int alloc_size; char *temppath, *writepath, *url; if( developer->integer ) silent = qfalse; if( !baseUrl || !baseUrl[0] || !filepath ) return qfalse; if( !strrchr( baseUrl, '/' ) ) { if( !silent ) Com_Printf( "SV_WebDownload: Invalid URL\n" ); return qfalse; } if( filepath[0] == '/' ) // filepath should never begin with a slash filepath++; if( !COM_ValidateRelativeFilename( filepath ) ) { if( !silent ) Com_Printf( "SV_WebDownload: Invalid filename\n" ); return qfalse; } if( !COM_FileExtension( filepath ) ) { if( !silent ) Com_Printf( "SV_WebDownload: no file extension\n" ); return qfalse; } // full url (baseurl + path) alloc_size = strlen( baseUrl ) + 1 + strlen( filepath ) + 1; url = Mem_TempMalloc( alloc_size ); if( baseUrl[ strlen( baseUrl ) - 1 ] == '/' ) // url includes last slash Q_snprintfz( url, alloc_size, "%s%s", baseUrl, filepath ); else Q_snprintfz( url, alloc_size, "%s/%s", baseUrl, filepath ); // add .tmp (relative + .tmp) alloc_size = strlen( filepath ) + strlen( ".tmp" ) + 1; temppath = Mem_TempMalloc( alloc_size ); Q_snprintfz( temppath, alloc_size, "%s.tmp", filepath ); // full write path for curl alloc_size = strlen( FS_WriteDirectory() ) + 1 + strlen( temppath ) + 1; writepath = Mem_TempMalloc( alloc_size ); Q_snprintfz( writepath, alloc_size, "%s/%s", FS_WriteDirectory(), temppath ); webDownloadPercentPrint = 0; webDownloadPercentStarted = qfalse; success = Web_Get( url, NULL, writepath, qtrue, 60 * 30, 60, SV_WebDownloadProgress, qfalse ); if( webDownloadPercentStarted ) Com_Printf( "\n" ); if( !success ) { if( !silent ) Com_Printf( "Failed to download remote file.\n" ); goto failed; } // rename the downloaded file if( !FS_MoveBaseFile( temppath, filepath ) ) { if( !overwrite ) { if( !silent ) Com_Printf( "Failed to rename temporary file.\n" ); goto failed; } // check if it failed because there already exists a file with the same name // and in this case remove this file if( FS_FOpenBaseFile( filepath, NULL, FS_READ ) != -1 ) { char *backfile; alloc_size = strlen( filepath ) + strlen( ".bak" ) + 1; backfile = Mem_TempMalloc( alloc_size ); Q_snprintfz( backfile, alloc_size, "%s.bak", filepath ); // if there is already a .bak file, destroy it if( FS_FOpenBaseFile( backfile, NULL, FS_READ ) != -1 ) FS_RemoveBaseFile( backfile ); // move the current file into .bak file if( !FS_MoveBaseFile( filepath, backfile ) ) { Mem_TempFree( backfile ); if( !silent ) Com_Printf( "Failed to backup destination file.\n" ); goto failed; } // now try renaming the downloaded file again if( !FS_MoveBaseFile( temppath, filepath ) ) { // didn't work, so restore the backup file if( FS_MoveBaseFile( backfile, filepath ) ) { if( !silent ) Com_Printf( "Failed to rename temporary file, restoring from backup.\n" ); } else { if( !silent ) Com_Printf( "Failed to rename temporary file and restore from backup.\n" ); } Mem_TempFree( backfile ); goto failed; } Mem_TempFree( backfile ); } } Mem_TempFree( temppath ); Mem_TempFree( writepath ); Mem_TempFree( url ); return qtrue; failed: if( !silent ) Com_Printf( "Removing temporary file: %s\n", writepath ); FS_RemoveAbsoluteFile( writepath ); Mem_TempFree( temppath ); Mem_TempFree( writepath ); Mem_TempFree( url ); return qfalse; }
/* * Finds or loads the given image */ gl3image_t * GL3_FindImage(char *name, imagetype_t type) { gl3image_t *image; int i, len; byte *pic; int width, height; char *ptr; char namewe[256]; int realwidth = 0, realheight = 0; const char* ext; if (!name) { return NULL; } ext = COM_FileExtension(name); if(!ext[0]) { /* file has no extension */ return NULL; } len = strlen(name); /* Remove the extension */ memset(namewe, 0, 256); memcpy(namewe, name, len - 4); if (len < 5) { return NULL; } /* fix backslashes */ while ((ptr = strchr(name, '\\'))) { *ptr = '/'; } /* look for it */ for (i = 0, image = gl3textures; i < numgl3textures; i++, image++) { if (!strcmp(name, image->name)) { image->registration_sequence = registration_sequence; return image; } } /* load the pic from disk */ pic = NULL; if (strcmp(ext, "pcx") == 0) { if (gl_retexturing->value) { GetPCXInfo(name, &realwidth, &realheight); if(realwidth == 0) { /* No texture found */ return NULL; } /* try to load a tga, png or jpg (in that order/priority) */ if ( LoadSTB(namewe, "tga", &pic, &width, &height) || LoadSTB(namewe, "png", &pic, &width, &height) || LoadSTB(namewe, "jpg", &pic, &width, &height) ) { /* upload tga or png or jpg */ image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } else { /* PCX if no TGA/PNG/JPEG available (exists always) */ LoadPCX(name, &pic, NULL, &width, &height); if (!pic) { /* No texture found */ return NULL; } /* Upload the PCX */ image = GL3_LoadPic(name, pic, width, 0, height, 0, type, 8); } } else /* gl_retexture is not set */ { LoadPCX(name, &pic, NULL, &width, &height); if (!pic) { return NULL; } image = GL3_LoadPic(name, pic, width, 0, height, 0, type, 8); } } else if (strcmp(ext, "wal") == 0) { if (gl_retexturing->value) { /* Get size of the original texture */ GetWalInfo(name, &realwidth, &realheight); if(realwidth == 0) { /* No texture found */ return NULL; } /* try to load a tga, png or jpg (in that order/priority) */ if ( LoadSTB(namewe, "tga", &pic, &width, &height) || LoadSTB(namewe, "png", &pic, &width, &height) || LoadSTB(namewe, "jpg", &pic, &width, &height) ) { /* upload tga or png or jpg */ image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } else { /* WAL if no TGA/PNG/JPEG available (exists always) */ image = LoadWal(namewe); } if (!image) { /* No texture found */ return NULL; } } else /* gl_retexture is not set */ { image = LoadWal(name); if (!image) { /* No texture found */ return NULL; } } } else if (strcmp(ext, "tga") == 0 || strcmp(ext, "png") == 0 || strcmp(ext, "jpg") == 0) { char tmp_name[256]; realwidth = 0; realheight = 0; strcpy(tmp_name, namewe); strcat(tmp_name, ".wal"); GetWalInfo(tmp_name, &realwidth, &realheight); if (realwidth == 0 || realheight == 0) { /* It's a sky or model skin. */ strcpy(tmp_name, namewe); strcat(tmp_name, ".pcx"); GetPCXInfo(tmp_name, &realwidth, &realheight); } /* TODO: not sure if not having realwidth/heigth is bad - a tga/png/jpg * was requested, after all, so there might be no corresponding wal/pcx? * if (realwidth == 0 || realheight == 0) return NULL; */ if(LoadSTB(name, ext, &pic, &width, &height)) { image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } } else { return NULL; } if (pic) { free(pic); } return image; }
/* * TV_Upstream_NextDemo */ void TV_Upstream_NextDemo( const char *demoname, const char *curdemo, qboolean randomize, char **name, char **filepath ) { int i, j, total; size_t bufsize, len, dir_size; char *file, *buf, **match, *dir; const char *extension, *pattern, *p; *name = *filepath = NULL; assert( demoname ); assert( *demoname ); buf = NULL; bufsize = 0; total = 0; // check if user specified a demo pattern (e.g. "tutorials/*.wd10") or a demolist filename extension = COM_FileExtension( demoname ); if( extension && !Q_stricmp( extension, APP_DEMO_EXTENSION_STR ) ) pattern = demoname; else pattern = ""; dir_size = strlen( "demos" ) + strlen( pattern ) + 1; dir = Mem_TempMalloc( dir_size ); strcpy( dir, "demos" ); if( *pattern ) { // find first character that looks like a wildcard const char *last_slash = NULL; p = pattern; do { if( *p == '/' ) last_slash = p; else if( *p == '?' || *p == '*' || *p == '[' ) break; } while( *++p ); // append the path part of wildcard to dir and shift the pattern if( last_slash ) { Q_strncatz( dir, "/", dir_size ); Q_strncatz( dir, pattern, strlen( dir ) + (last_slash - pattern) + 1 ); pattern = last_slash + 1; } bufsize = 0; total = FS_GetFileListExt( dir, APP_DEMO_EXTENSION_STR, NULL, &bufsize, 0, 0 ); if( !total ) bufsize = 0; if( bufsize ) { buf = Mem_TempMalloc( bufsize ); FS_GetFileList( dir, APP_DEMO_EXTENSION_STR, buf, bufsize, 0, 0 ); } } else { // load demolist file and pick next available demo int filehandle = 0, filelen = -1; // load list from file filelen = FS_FOpenFile( demoname, &filehandle, FS_READ ); if( filehandle && filelen > 0 ) { bufsize = (size_t)(filelen + 1); buf = Mem_TempMalloc( bufsize ); FS_Read( buf, filelen, filehandle ); FS_FCloseFile( filehandle ); } // parse the list stripping CRLF characters if( buf ) { p = strtok( buf, "\r\n" ); if( p ) { char *newbuf; size_t newbufsize; newbufsize = 0; newbuf = Mem_TempMalloc( bufsize ); while( p != NULL ) { total++; Q_strncpyz( newbuf + newbufsize, p, bufsize - newbufsize ); newbufsize += strlen( p ) + 1; p = strtok( NULL, "\r\n" ); } Mem_TempFree( buf ); buf = newbuf; } } } if( buf ) { int next; // get the list of demo files match = Mem_TempMalloc( total * sizeof( char * ) ); total = 0; next = (randomize ? -1 : 0); for( len = 0; buf[len]; ) { file = buf + len; len += strlen( file ) + 1; if( *pattern ) { if( !Com_GlobMatch( pattern, file, qfalse ) ) continue; } // avoid replays if( curdemo && !Q_stricmp( file, curdemo ) ) { // if ordered, schedule the next map if( !randomize ) next = total; continue; } match[total++] = file; } // pick a new random demo if possible or otherwise try the old one if( total ) { if( next < 0 ) next = rand() % total; // walk the list until we find an existing file // in case of pattern match, the check is not necessary though for( i = 0; i < total; i++ ) { j = (i + next) % total; if( !*pattern ) { extension = COM_FileExtension( match[j] ); if( FS_FOpenFile( va( "demos/%s%s", match[j], (extension ? "" : APP_DEMO_EXTENSION_STR) ), NULL, FS_READ ) == -1 ) continue; } *name = TempCopyString( match[j] ); break; } } // fallback to current demo if( !*name && curdemo ) *name = TempCopyString( curdemo ); Mem_TempFree( match ); // append the dir to filename, sigh.. if( *name ) { size_t filepath_size; filepath_size = strlen( dir ) + strlen( "/" ) + strlen( *name ) + strlen( APP_DEMO_EXTENSION_STR ) + 1; *filepath = Mem_TempMalloc( filepath_size ); strcpy( *filepath, dir ); strcat( *filepath, "/" ); strcat( *filepath, *name ); COM_DefaultExtension( *filepath, APP_DEMO_EXTENSION_STR, filepath_size ); } Mem_TempFree( buf ); } Mem_TempFree( dir ); }
void S_StartBackgroundTrack( const char *intro, const char *loop ) { int count; const char *ext; bgTrack_t *t, f; bgTrack_t *introTrack, *loopTrack; ALenum error; int mode = 0; // Stop any existing music that might be playing S_StopBackgroundTrack(); if( !intro || !intro[0] ) return; s_bgTrackPaused = qfalse; ext = COM_FileExtension( intro ); if( ext && !Q_stricmp( ext, ".m3u" ) ) { // mode bits: // 1 - shuffle // 2 - loop the selected track if( loop && loop[0] ) mode = atoi( loop ); if( S_ReadPlaylistFile( intro, mode & 1 ? qtrue : qfalse ) ) goto start_playback; } // the intro track loops unless another loop track has been specified introTrack = S_AllocTrack( intro ); introTrack->next = introTrack->prev = introTrack; if( loop && loop[0] && Q_stricmp( intro, loop ) ) { loopTrack = S_AllocTrack( loop ); if( S_OpenMusicTrack( loopTrack ) ) { S_CloseMusicTrack( loopTrack ); loopTrack->next = introTrack->next = introTrack->prev = loopTrack; loopTrack->prev = introTrack; } } s_bgTrack = introTrack; start_playback: // this effectively precaches the first 15 scheduled tracks in the playlist for( count = 0, t = s_bgTrack; count < 15 && t && t != s_bgTrack; count++ ) { if( !t->isUrl ) { S_OpenMusicTrack( t ); if( t->next == t || t->next == s_bgTrack ) break; // break on an endless loop or full cycle if( !t->ignore && ( mode & 2 ) ) { // no point in precaching the whole playlist when we're only going // to loop one single track break; } } t = t->next; } // start playback with the first valid track if( count > 1 ) { memset( &f, 0, sizeof( f ) ); f.next = s_bgTrack; s_bgTrack = S_NextMusicTrack( &f ); } else { S_OpenMusicTrack( s_bgTrack ); } if( !s_bgTrack || s_bgTrack->ignore ) { S_StopBackgroundTrack(); return; } if( mode & 2 ) { // loop the same track over and over s_bgTrack->next = s_bgTrack->prev = s_bgTrack; } music_source_get(); if( !src ) { Com_Printf( "Error couldn't get source for music\n" ); S_StopBackgroundTrack(); return; } alloced_buffers = qfalse; queued_buffers = qfalse; qalGenBuffers( MUSIC_BUFFERS, buffers ); if( ( error = qalGetError() ) != AL_NO_ERROR ) { Com_Printf( "Error couldn't generate music buffers (%s)\n", S_ErrorMessage( error ) ); S_StopBackgroundTrack(); return; } alloced_buffers = qtrue; }
/* * CL_DownloadRequest * * Request file download * return false if couldn't request it for some reason * Files with .pk3 or .pak extension have to have gamedir attached * Other files must not have gamedir */ bool CL_DownloadRequest( const char *filename, bool requestpak ) { if( cls.download.requestname ) { Com_Printf( "Can't download: %s. Download already in progress.\n", filename ); return false; } if( !COM_ValidateRelativeFilename( filename ) ) { Com_Printf( "Can't download: %s. Invalid filename.\n", filename ); return false; } if( FS_CheckPakExtension( filename ) ) { if( FS_PakFileExists( filename ) ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return false; } if( !Q_strnicmp( COM_FileBase( filename ), "modules", strlen( "modules" ) ) ) { if( !CL_CanDownloadModules() ) return false; } } else { if( FS_FOpenFile( filename, NULL, FS_READ ) != -1 ) { Com_Printf( "Can't download: %s. File already exists.\n", filename ); return false; } if( !requestpak ) { const char *extension; // only allow demo downloads extension = COM_FileExtension( filename ); if( !extension || Q_stricmp( extension, APP_DEMO_EXTENSION_STR ) ) { Com_Printf( "Can't download, got arbitrary file type: %s\n", filename ); return false; } } } if( cls.socket->type == SOCKET_LOOPBACK ) { Com_DPrintf( "Can't download: %s. Loopback server.\n", filename ); return false; } Com_Printf( "Asking to download: %s\n", filename ); cls.download.requestpak = requestpak; cls.download.requestname = Mem_ZoneMalloc( sizeof( char ) * ( strlen( filename ) + 1 ) ); Q_strncpyz( cls.download.requestname, filename, sizeof( char ) * ( strlen( filename ) + 1 ) ); cls.download.timeout = Sys_Milliseconds() + 5000; CL_AddReliableCommand( va( "download %i \"%s\"", requestpak, filename ) ); return true; }
/* ================= Sys_ListFiles_r Internal function to filesystem. Conventions apply: - files should hold at least MAX_LISTED_FILES - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1] - depth must be 0 on the first call ================= */ void Sys_ListFiles_r(const char *path, const char *filter, unsigned flags, size_t baselen, int *count_p, void **files, int depth) { struct dirent *ent; DIR *dir; struct stat st; char fullpath[MAX_OSPATH]; char *name; size_t len; void *info; if ((dir = opendir(path)) == NULL) { return; } while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') { continue; // ignore dotfiles } len = Q_concat(fullpath, sizeof(fullpath), path, "/", ent->d_name, NULL); if (len >= sizeof(fullpath)) { continue; } st.st_mode = 0; #ifdef _DIRENT_HAVE_D_TYPE // try to avoid stat() if possible if (!(flags & FS_SEARCH_EXTRAINFO) && ent->d_type != DT_UNKNOWN && ent->d_type != DT_LNK) { st.st_mode = DTTOIF(ent->d_type); } #endif if (st.st_mode == 0 && stat(fullpath, &st) == -1) { continue; } // pattern search implies recursive search if ((flags & FS_SEARCH_BYFILTER) && S_ISDIR(st.st_mode) && depth < MAX_LISTED_DEPTH) { Sys_ListFiles_r(fullpath, filter, flags, baselen, count_p, files, depth + 1); // re-check count if (*count_p >= MAX_LISTED_FILES) { break; } } // check type if (flags & FS_SEARCH_DIRSONLY) { if (!S_ISDIR(st.st_mode)) { continue; } } else { if (!S_ISREG(st.st_mode)) { continue; } } // check filter if (filter) { if (flags & FS_SEARCH_BYFILTER) { if (!FS_WildCmp(filter, fullpath + baselen)) { continue; } } else { if (!FS_ExtCmp(filter, ent->d_name)) { continue; } } } // strip path if (flags & FS_SEARCH_SAVEPATH) { name = fullpath + baselen; } else { name = ent->d_name; } // strip extension if (flags & FS_SEARCH_STRIPEXT) { *COM_FileExtension(name) = 0; if (!*name) { continue; } } // copy info off if (flags & FS_SEARCH_EXTRAINFO) { info = FS_CopyInfo(name, st.st_size, st.st_ctime, st.st_mtime); } else { info = FS_CopyString(name); } files[(*count_p)++] = info; if (*count_p >= MAX_LISTED_FILES) { break; } } closedir(dir); }
// // keys handling // returns: true if processed, false if ignored // qbool FL_Key(filelist_t *fl, int key) { if (fl->mode != FL_MODE_NORMAL) { switch(key) { case 'y': case 'Y': case K_ENTER: if (!FL_IsCurrentDir(fl)) { if (fl->mode == FL_MODE_DELETE) { FL_DeleteFile(fl); } #ifdef WITH_ZIP else if (fl->mode == FL_MODE_COMPRESS) { FL_CompressFile(fl); // Compress file. } else if (fl->mode == FL_MODE_DECOMPRESS) { FL_DecompressFile(fl); // Decompress file. } #endif // WITH_ZIP } fl->mode = FL_MODE_NORMAL; return true; case 'n': case 'N': case K_ESCAPE: fl->mode = FL_MODE_NORMAL; return true; } return false; } // Check for search if ((key >= ' ' && key <= '~') && (fl->search_valid || (!isAltDown() && !isCtrlDown() && !isShiftDown()))) { int len; if (!fl->search_valid) { // Start searching fl->search_valid = true; fl->search_error = false; fl->search_string[0] = 0; } len = strlen(fl->search_string); if (len < MAX_SEARCH_STRING && !fl->search_error) { fl->search_string[len] = key; fl->search_string[len+1] = 0; fl->search_dirty = true; // Save the last time the user entered a char in the // search term, so that we know when to timeout the search prompt. // (See beginning of FL_Draw) last_search_enter_time = Sys_DoubleTime(); } return true; // handled } else { fl->search_valid = false; // finish search mode } // sorting mode / displaying columns if (key >= '1' && key <= '4') { if (isCtrlDown() && !isAltDown() && !isShiftDown()) { switch (key) { case '2': Cvar_Toggle(&file_browser_show_size); break; case '3': Cvar_Toggle(&file_browser_show_date); break; case '4': Cvar_Toggle(&file_browser_show_time); break; default: break; } return true; } else if (!isCtrlDown() && isAltDown() && !isShiftDown()) { char buf[128]; strlcpy(buf, file_browser_sort_mode.string, 32); // WTF? if (key == buf[0]) { // reverse order buf[0] ^= 128; } else { // add new memmove(buf+1, buf, strlen(buf)+1); buf[0] = key; } buf[8] = 0; Cvar_Set(&file_browser_sort_mode, buf); fl->need_resort = true; return true; } } // change drive #ifdef _WIN32 if (isAltDown() && isCtrlDown() && tolower(key) >= 'a' && tolower(key) <= 'z') { char newdir[MAX_PATH+1]; char olddir[MAX_PATH+1]; snprintf(newdir, sizeof (newdir), "%c:\\", tolower(key)); // validate if (Sys_getcwd(olddir, MAX_PATH+1) == 0) return true; if (Sys_chdir(newdir) == 0) return true; Sys_chdir(olddir); // and set FL_SetCurrentDir(fl, newdir); fl->need_refresh = true; return true; } #endif if (key == '\\' || key == '/') { FL_ChangeDir(fl, va("%c", PATH_SEPARATOR)); return true; } if (key == K_ENTER || key == K_MOUSE1) { if (FL_IsCurrentDir(fl)) { FL_ChangeDir(fl, FL_GetCurrentPath(fl)); return true; } #ifdef WITH_ZIP else if (FL_IsCurrentArchive(fl)) { FL_ChangeArchive(fl, FL_GetCurrentPath(fl)); return true; } #endif //WITH_ZIP else { return false; } } if (key == K_BACKSPACE) { if (fl->show_dirup) FL_ChangeDir(fl, ".."); return true; } if (key == K_UPARROW || key == K_MWHEELUP) { fl->current_entry--; FL_CheckDisplayPosition(fl); return true; } if (key == K_DOWNARROW || key == K_MWHEELDOWN) { fl->current_entry++; FL_CheckDisplayPosition(fl); return true; } if (key == K_PGUP) { fl->current_entry -= fl->last_page_size; FL_CheckDisplayPosition(fl); return true; } if (key == K_PGDN) { fl->current_entry += fl->last_page_size; FL_CheckDisplayPosition(fl); return true; } if (key == K_HOME) { fl->current_entry = 0; FL_CheckDisplayPosition(fl); return true; } if (key == K_END) { fl->current_entry = fl->num_entries - 1; FL_CheckDisplayPosition(fl); return true; } #ifdef WITH_ZIP // // Compress the current file. // if ((key == 'c' || key == 'C') && isAltDown()) { if (!FL_IsCurrentDir(fl)) { if (isShiftDown()) { // Alt + shift + c == Compress without confirming. FL_CompressFile(fl); } else { // Alt + c == Confirm before compressing. fl->mode = FL_MODE_COMPRESS; } } return true; } // // Decompress the current file. // if ((key == 'd' || key == 'D') && isAltDown()) { if (!strcmp(COM_FileExtension(FL_GetCurrentPath(fl)), "gz")) { FL_DecompressFile(fl); } } #endif // WITH_ZIP // // Delete the current file. // if (key == K_DEL) { if (!FL_IsCurrentDir(fl)) { if (isShiftDown()) { // Shift + del == Delete without confirming. FL_DeleteFile(fl); } else { // Del == Confirm before deleting. fl->mode = FL_MODE_DELETE; } } return true; } return false; }
void FL_StripFileName(filelist_t *fl, filedesc_t *f) { int i; char namebuf[_MAX_FNAME] = {0}; char extbuf[_MAX_EXT] = {0}; char *t; // Don't try to strip this. if (!strcmp(f->name, "..")) { strlcpy (f->display, "/..", sizeof(f->display)); return; } // Common for dir/file, get name without path but with ext strlcpy (namebuf, COM_SkipPath (f->name), sizeof (namebuf)); // File specific. if (!f->is_directory) { // Get extension. snprintf (extbuf, sizeof(extbuf), ".%s", COM_FileExtension (namebuf)); // If the extension is only a . it means we have no extension. if (strlen (extbuf) == 1) { extbuf[0] = '\0'; } // Remove extension from the name. COM_StripExtension(namebuf, namebuf); } if (file_browser_strip_names.value && !f->is_directory) { char *s; for (i=0; i < strlen(namebuf); i++) if (namebuf[i] == '_') namebuf[i] = ' '; // Remove spaces from the beginning s = namebuf; while (*s == ' ') s++; memmove(namebuf, s, strlen(s) + 1); // Remove spaces from the end s = namebuf + strlen(namebuf); while (s > namebuf && *(s-1) == ' ') s--; *s = 0; // Remove few spaces in a row s = namebuf; while (s < namebuf + strlen(namebuf)) { if (*s == ' ') { char *q = s+1; while (*q == ' ') q++; if (q > s+1) memmove(s+1, q, strlen(q)+1); } s++; } if (namebuf[0] == 0) strlcpy (namebuf, "_", sizeof (namebuf)); } // Replace all non-standard characters with '_' for (i=0; i < strlen(namebuf); i++) { if (namebuf[i] < ' ' || namebuf[i] > '~') namebuf[i] = '_'; } f->display[0] = 0; t = f->display; // Add a slash before a dir. if (f->is_directory) *t++ = '/'; // Add the name and extension to the final buffer. for (i=0; i < strlen(namebuf) && (t - f->display) < MAX_PATH; i++) *t++ = namebuf[i]; for (i=0; i < strlen(extbuf) && (t - f->display) < MAX_PATH; i++) *t++ = extbuf[i]; *t = 0; }
/* ==================== CL_PlayDemo_f play [demoname] ==================== */ void CL_PlayDemo_f (void) { char name[256]; qbool try_dem; if (Cmd_Argc() != 2) { Com_Printf ("playdemo <demoname> : plays a demo\n"); return; } // // disconnect from server // Host_EndGame (); // // open the demo file // strlcpy (name, Cmd_Argv(1), sizeof(name)-4); #ifdef _WIN32 if (strlen(name) > 4 && !Q_stricmp(name + strlen(name) - 4, ".qwz")) { PlayQWZDemo (); return; } #endif if (COM_FileExtension(name)[0] == 0) { COM_DefaultExtension (name, ".qwd"); try_dem = true; // if we can't open the .qwd, try .dem also } else try_dem = false; try_again: if (!strncmp(name, "../", 3) || !strncmp(name, "..\\", 3)) cls.demofile = fopen (va("%s/%s", com_basedir, name+3), "rb"); else FS_FOpenFile (name, &cls.demofile); if (!cls.demofile && try_dem) { COM_StripExtension (name, name); strcat (name, ".dem"); try_dem = false; goto try_again; } if (!cls.demofile) { Com_Printf ("ERROR: couldn't open \"%s\"\n", Cmd_Argv(1)); cls.playdemos = 0; return; } Com_Printf ("Playing demo from %s.\n", COM_SkipPath(name)); cls.nqdemoplayback = !Q_stricmp(COM_FileExtension(name), "dem"); if (cls.nqdemoplayback) { NQD_StartPlayback (); } #ifdef MVDPLAY cls.mvdplayback = !Q_stricmp(COM_FileExtension(name), "mvd"); #endif cls.demoplayback = true; cls.state = ca_demostart; Netchan_Setup (NS_CLIENT, &cls.netchan, net_null, 0); cls.demotime = 0; #ifdef MVDPLAY cls.mvd_newtime = cls.mvd_oldtime = 0; cls.mvd_findtarget = true; cls.mvd_lasttype = 0; cls.mvd_lastto = 0; MVD_ClearPredict(); #endif }
/* ================= Sys_ListFiles_r Internal function to filesystem. Conventions apply: - files should hold at least MAX_LISTED_FILES - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1] - depth must be 0 on the first call ================= */ void Sys_ListFiles_r(const char *path, const char *filter, unsigned flags, size_t baselen, int *count_p, void **files, int depth) { WIN32_FIND_DATAA data; HANDLE handle; char fullpath[MAX_OSPATH], *name; size_t pathlen, len; unsigned mask; void *info; // optimize single extension search if (!(flags & FS_SEARCH_BYFILTER) && filter && !strchr(filter, ';')) { if (*filter == '.') { filter++; } len = Q_concat(fullpath, sizeof(fullpath), path, "\\*.", filter, NULL); filter = NULL; // do not check it later } else { len = Q_concat(fullpath, sizeof(fullpath), path, "\\*", NULL); } if (len >= sizeof(fullpath)) { return; } // format path to windows style // done on the first run only if (!depth) { FS_ReplaceSeparators(fullpath, '\\'); } handle = FindFirstFileA(fullpath, &data); if (handle == INVALID_HANDLE_VALUE) { return; } // make it point right after the slash pathlen = strlen(path) + 1; do { if (!strcmp(data.cFileName, ".") || !strcmp(data.cFileName, "..")) { continue; // ignore special entries } // construct full path len = strlen(data.cFileName); if (pathlen + len >= sizeof(fullpath)) { continue; } memcpy(fullpath + pathlen, data.cFileName, len + 1); if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { mask = FS_SEARCH_DIRSONLY; } else { mask = 0; } // pattern search implies recursive search if ((flags & FS_SEARCH_BYFILTER) && mask && depth < MAX_LISTED_DEPTH) { Sys_ListFiles_r(fullpath, filter, flags, baselen, count_p, files, depth + 1); // re-check count if (*count_p >= MAX_LISTED_FILES) { break; } } // check type if ((flags & FS_SEARCH_DIRSONLY) != mask) { continue; } // check filter if (filter) { if (flags & FS_SEARCH_BYFILTER) { if (!FS_WildCmp(filter, fullpath + baselen)) { continue; } } else { if (!FS_ExtCmp(filter, data.cFileName)) { continue; } } } // strip path if (flags & FS_SEARCH_SAVEPATH) { name = fullpath + baselen; } else { name = data.cFileName; } // reformat it back to quake filesystem style FS_ReplaceSeparators(name, '/'); // strip extension if (flags & FS_SEARCH_STRIPEXT) { *COM_FileExtension(name) = 0; if (!*name) { continue; } } // copy info off if (flags & FS_SEARCH_EXTRAINFO) { info = copy_info(name, &data); } else { info = FS_CopyString(name); } files[(*count_p)++] = info; } while (*count_p < MAX_LISTED_FILES && FindNextFileA(handle, &data) != FALSE); FindClose(handle); }