qboolean COM_IsPath( const char *s ) { int c; if( !*s ) { return qfalse; } do { c = *s++; if( !Q_ispath( c ) ) { return qfalse; } } while( *s ); return qtrue; }
// Validate a path supplied by a filelist. static void check_and_queue_download(char *path) { size_t len; char *ext; dltype_t type; unsigned flags; int valid; len = strlen(path); if (len >= MAX_QPATH) return; ext = strrchr(path, '.'); if (!ext) return; ext++; if (!ext[0]) return; Q_strlwr(ext); if (!strcmp(ext, "pak") || !strcmp(ext, "pkz")) { Com_Printf("[HTTP] Filelist is requesting a .%s file '%s'\n", ext, path); type = DL_PAK; } else { type = DL_OTHER; if (!CL_CheckDownloadExtension(ext)) { Com_WPrintf("[HTTP] Illegal file type '%s' in filelist.\n", path); return; } } if (path[0] == '@') { if (type == DL_PAK) { Com_WPrintf("[HTTP] '@' prefix used on a pak file '%s' in filelist.\n", path); return; } flags = FS_PATH_GAME; path++; len--; } else if (type == DL_PAK) { //by definition paks are game-local flags = FS_PATH_GAME | FS_TYPE_REAL; } else { flags = 0; } len = FS_NormalizePath(path, path); if (len == 0) return; valid = FS_ValidatePath(path); if (valid == PATH_INVALID || !Q_ispath(path[0]) || !Q_ispath(path[len - 1]) || strstr(path, "..") || (type == DL_OTHER && !strchr(path, '/')) || (type == DL_PAK && strchr(path, '/'))) { Com_WPrintf("[HTTP] Illegal path '%s' in filelist.\n", path); return; } if (FS_FileExistsEx(path, flags)) return; if (valid == PATH_MIXED_CASE) Q_strlwr(path); if (CL_IgnoreDownload(path)) return; CL_QueueDownload(path, type); }