diff --git a/libs/os/path.h b/libs/os/path.h index 286cf160..14f17c07 100644 --- a/libs/os/path.h +++ b/libs/os/path.h @@ -272,8 +272,7 @@ TextOutputStreamType& ostream_write( TextOutputStreamType& ostream, const Direct ostream << *i; } } - --i; - if ( *i != '/' && *i != '\\' ) { + if ( !path_separator( *--i ) ) { ostream << '/'; } } diff --git a/tools/quake3/common/aselib.cpp b/tools/quake3/common/aselib.cpp index 73f73486..b115f0d8 100644 --- a/tools/quake3/common/aselib.cpp +++ b/tools/quake3/common/aselib.cpp @@ -24,6 +24,7 @@ #include "cmdlib.h" #include "inout.h" #include "qstringops.h" +#include "qpathops.h" #include #include diff --git a/tools/quake3/common/cmdlib.cpp b/tools/quake3/common/cmdlib.cpp index 72e3d891..e72272d5 100644 --- a/tools/quake3/common/cmdlib.cpp +++ b/tools/quake3/common/cmdlib.cpp @@ -31,8 +31,10 @@ #include "cmdlib.h" #include "inout.h" #include "qstringops.h" +#include "qpathops.h" #include #include +#include #ifdef WIN32 #include @@ -424,35 +426,6 @@ int LoadFile( const char *filename, void **bufferptr ){ } -/* - ============== - LoadFileBlock - - - rounds up memory allocation to 4K boundary - - - ============== - */ -int LoadFileBlock( const char *filename, void **bufferptr ){ - FILE *f; - int length, nBlock, nAllocSize; - void *buffer; - - f = SafeOpenRead( filename ); - length = Q_filelength( f ); - nAllocSize = length; - nBlock = nAllocSize % MEM_BLOCKSIZE; - if ( nBlock > 0 ) { - nAllocSize += MEM_BLOCKSIZE - nBlock; - } - buffer = safe_calloc( nAllocSize + 1 ); - SafeRead( f, buffer, length ); - fclose( f ); - - *bufferptr = buffer; - return length; -} - - /* ============== TryLoadFile @@ -496,86 +469,6 @@ void SaveFile( const char *filename, const void *buffer, int count ){ } -/* - ==================== - Extract file parts - ==================== - */ - -/// \brief Returns a pointer to the last slash or to terminating null character if not found. -const char* path_get_last_separator( const char* path ){ - const char *end = path + strlen( path ); - const char *src = end; - - while ( src != path ){ - if( path_separator( *--src ) ) - return src; - } - return end; -} - -char* path_get_last_separator( char* path ){ - return const_cast( path_get_last_separator( const_cast( path ) ) ); -} - -/// \brief Appends trailing slash, unless \p path is empty or already has slash. -void path_add_slash( char *path ){ - char* end = path + strlen( path ); - if ( end != path && !path_separator( end[-1] ) ) - strcat( end, "/" ); -} - -/// \brief Appends or replaces .EXT part of \p path with \p extension. -void path_set_extension( char *path, const char *extension ){ - strcpy( path_get_filename_base_end( path ), extension ); -} - -// -// if path doesnt have a .EXT, append extension -// (extension should include the .) -// -void DefaultExtension( char *path, const char *extension ){ - char* ext = path_get_filename_base_end( path ); - if( strEmpty( ext ) ) - strcpy( ext, extension ); -} - - -void DefaultPath( char *path, const char *basepath ){ - if( !path_is_absolute( path ) ){ - char* temp = strdup( path ); - sprintf( path, "%s%s", basepath, temp ); - free( temp ); - } -} - - -void StripFilename( char *path ){ - strClear( path_get_filename_start( path ) ); -} - -void StripExtension( char *path ){ - strClear( path_get_filename_base_end( path ) ); -} - - -// NOTE: includes the slash, otherwise -// backing to an empty path will be wrong when appending a slash -void ExtractFilePath( const char *path, char *dest ){ - strcpyQ( dest, path, path_get_filename_start( path ) - path + 1 ); // +1 for '\0' -} - -void ExtractFileBase( const char *path, char *dest ){ - const char* start = path_get_filename_start( path ); - const char* end = path_get_filename_base_end( start ); - strcpyQ( dest, start, end - start + 1 ); // +1 for '\0' -} - -void ExtractFileExtension( const char *path, char *dest ){ - strcpy( dest, path_get_extension( path ) ); -} - - /* ============== ParseNum / ParseHex diff --git a/tools/quake3/common/cmdlib.h b/tools/quake3/common/cmdlib.h index f12ee7a7..44e1f7c4 100644 --- a/tools/quake3/common/cmdlib.h +++ b/tools/quake3/common/cmdlib.h @@ -21,38 +21,12 @@ // cmdlib.h -#ifndef __CMDLIB__ -#define __CMDLIB__ +#pragma once #include "bytebool.h" -#ifdef _MSC_VER -#pragma warning(disable : 4244) // MIPS -#pragma warning(disable : 4136) // X86 -#pragma warning(disable : 4051) // ALPHA - -#pragma warning(disable : 4018) // signed/unsigned mismatch -#pragma warning(disable : 4305) // truncate from double to float - -#pragma check_stack(off) - -#endif - #include -#include #include -#include -#include -#include -#include - -#include "os/path.h" - -#ifdef _MSC_VER - -#pragma intrinsic( memset, memcpy ) - -#endif #ifdef PATH_MAX @@ -60,7 +34,6 @@ #else #define MAX_OS_PATH 4096 #endif -#define MEM_BLOCKSIZE 4096 #define SAFE_MALLOC #ifdef SAFE_MALLOC @@ -115,31 +88,11 @@ void SafeRead( FILE *f, void *buffer, int count ); void SafeWrite( FILE *f, const void *buffer, int count ); int LoadFile( const char *filename, void **bufferptr ); -int LoadFileBlock( const char *filename, void **bufferptr ); int TryLoadFile( const char *filename, void **bufferptr ); void SaveFile( const char *filename, const void *buffer, int count ); bool FileExists( const char *filename ); -const char* path_get_last_separator( const char* path ); - char* path_get_last_separator( char* path ); -void path_add_slash( char *path ); -void path_set_extension( char *path, const char *extension ); -void DefaultExtension( char *path, const char *extension ); -void DefaultPath( char *path, const char *basepath ); -void StripFilename( char *path ); -void StripExtension( char *path ); - -static inline void FixDOSName( char *src ){ - for ( ; *src; ++src ) - if ( *src == '\\' ) - *src = '/'; -} - -void ExtractFilePath( const char *path, char *dest ); // file directory with trailing slash -void ExtractFileBase( const char *path, char *dest ); // file name w/o extension -void ExtractFileExtension( const char *path, char *dest ); - int ParseNum( const char *str ); short BigShort( short l ); @@ -159,13 +112,3 @@ void QCopyFile( const char *from, const char *to ); // sleep for the given amount of milliseconds void Sys_Sleep( int n ); - -// for compression routines -typedef struct -{ - void *data; - int count, width, height; -} cblock_t; - - -#endif diff --git a/tools/quake3/common/imagelib.cpp b/tools/quake3/common/imagelib.cpp index ad819e05..15339539 100644 --- a/tools/quake3/common/imagelib.cpp +++ b/tools/quake3/common/imagelib.cpp @@ -24,6 +24,7 @@ #include "inout.h" #include "cmdlib.h" #include "qstringops.h" +#include "qpathops.h" #include "etclib.h" #include "imagelib.h" #include "vfs.h" diff --git a/tools/quake3/common/inout.cpp b/tools/quake3/common/inout.cpp index 07d9b90f..6a5a181e 100644 --- a/tools/quake3/common/inout.cpp +++ b/tools/quake3/common/inout.cpp @@ -30,6 +30,7 @@ #include "inout.h" #include #include +#include #include "generic/vector.h" #ifdef WIN32 diff --git a/tools/quake3/common/polylib.cpp b/tools/quake3/common/polylib.cpp index 19503681..8bf743fc 100644 --- a/tools/quake3/common/polylib.cpp +++ b/tools/quake3/common/polylib.cpp @@ -21,6 +21,7 @@ #include +#include #include "cmdlib.h" #include "inout.h" diff --git a/tools/quake3/common/qpathops.h b/tools/quake3/common/qpathops.h new file mode 100644 index 00000000..ae0dfd9c --- /dev/null +++ b/tools/quake3/common/qpathops.h @@ -0,0 +1,105 @@ +/* + Copyright (C) 1999-2006 Id Software, Inc. and contributors. + For a list of contributors, see the accompanying CONTRIBUTORS file. + + This file is part of GtkRadiant. + + GtkRadiant is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + GtkRadiant is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GtkRadiant; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// cmdlib.h + +#pragma once + +#include "os/path.h" +#include "qstringops.h" + +/* + ==================== + Extract file parts + ==================== + */ + +/// \brief Returns a pointer to the last slash or to terminating null character if not found. +inline const char* path_get_last_separator( const char* path ){ + const char *end = path + strlen( path ); + const char *src = end; + + while ( src != path ){ + if( path_separator( *--src ) ) + return src; + } + return end; +} + +inline char* path_get_last_separator( char* path ){ + return const_cast( path_get_last_separator( const_cast( path ) ) ); +} + +/// \brief Appends trailing slash, unless \p path is empty or already has slash. +inline void path_add_slash( char *path ){ + char* end = path + strlen( path ); + if ( end != path && !path_separator( end[-1] ) ) + strcat( end, "/" ); +} + +/// \brief Appends or replaces .EXT part of \p path with \p extension. +inline void path_set_extension( char *path, const char *extension ){ + strcpy( path_get_filename_base_end( path ), extension ); +} + +// +// if path doesnt have a .EXT, append extension +// (extension should include the .) +// +inline void DefaultExtension( char *path, const char *extension ){ + char* ext = path_get_filename_base_end( path ); + if( strEmpty( ext ) ) + strcpy( ext, extension ); +} + + +inline void StripFilename( char *path ){ + strClear( path_get_filename_start( path ) ); +} + +inline void StripExtension( char *path ){ + strClear( path_get_filename_base_end( path ) ); +} + + +inline void FixDOSName( char *src ){ + for ( ; *src; ++src ) + if ( *src == '\\' ) + *src = '/'; +} + +// file directory with trailing slash +// NOTE: includes the slash, otherwise +// backing to an empty path will be wrong when appending a slash +inline void ExtractFilePath( const char *path, char *dest ){ + strcpyQ( dest, path, path_get_filename_start( path ) - path + 1 ); // +1 for '\0' +} + +// file name w/o extension +inline void ExtractFileBase( const char *path, char *dest ){ + const char* start = path_get_filename_start( path ); + const char* end = path_get_filename_base_end( start ); + strcpyQ( dest, start, end - start + 1 ); // +1 for '\0' +} + +inline void ExtractFileExtension( const char *path, char *dest ){ + strcpy( dest, path_get_extension( path ) ); +} diff --git a/tools/quake3/common/scriplib.cpp b/tools/quake3/common/scriplib.cpp index 6633de34..0aa465a6 100644 --- a/tools/quake3/common/scriplib.cpp +++ b/tools/quake3/common/scriplib.cpp @@ -24,6 +24,7 @@ #include "cmdlib.h" #include "inout.h" #include "qstringops.h" +#include "qpathops.h" #include "scriplib.h" #include "vfs.h" diff --git a/tools/quake3/common/vfs.cpp b/tools/quake3/common/vfs.cpp index bfb7d2dd..cceac5f5 100644 --- a/tools/quake3/common/vfs.cpp +++ b/tools/quake3/common/vfs.cpp @@ -41,12 +41,27 @@ // Leonardo Zide (leo@lokigames.com) // +#if defined ( __linux__ ) || defined ( __APPLE__ ) +#include +#include +#include +#else +#include + +#ifndef R_OK +#define R_OK 04 +#endif + +#endif + #include #include #include +#include #include "cmdlib.h" #include "qstringops.h" +#include "qpathops.h" #include "filematch.h" #include "inout.h" #include "vfs.h" @@ -80,10 +95,8 @@ struct VFS_PAKFILE static std::forward_list g_paks; static std::forward_list g_pakFiles; -static char g_strDirs[VFS_MAXDIRS][PATH_MAX + 1]; -static int g_numDirs; -char g_strForbiddenDirs[VFS_MAXDIRS][PATH_MAX + 1]; -int g_numForbiddenDirs = 0; +static std::vector g_strDirs; +std::vector g_strForbiddenDirs; static constexpr bool g_bUsePak = true; char g_strLoadedFileLocation[1024]; @@ -147,31 +160,26 @@ static void vfsInitPakFile( const char *filename ){ // reads all pak files from a dir void vfsInitDirectory( const char *path ){ GDir *dir; - int j; - for ( j = 0; j < g_numForbiddenDirs; ++j ) + const auto path_is_forbidden = []( const char *path ){ + for ( const auto& forbidden : g_strForbiddenDirs ) + if ( matchpattern( path_get_filename_start( path ), forbidden.c_str(), TRUE ) ) + return true; + return false; + }; + { - char* dbuf = strdup( path ); - if ( !strEmpty( dbuf ) && path_separator( dbuf[strlen( dbuf ) - 1] ) ) // del trailing slash - strClear( &dbuf[strlen( dbuf ) - 1] ); - if ( matchpattern( path_get_filename_start( dbuf ), g_strForbiddenDirs[j], TRUE ) ) { - free( dbuf ); + StringBuffer buf( path ); + if ( !buf.empty() && path_separator( buf.back() ) ) // del trailing slash + buf.pop_back(); + if ( path_is_forbidden( buf.c_str() ) ) return; - } - free( dbuf ); - } - - if ( g_numDirs == VFS_MAXDIRS ) { - return; } Sys_Printf( "VFS Init: %s\n", path ); - strncpy( g_strDirs[g_numDirs], path, PATH_MAX ); - g_strDirs[g_numDirs][PATH_MAX] = 0; - FixDOSName( g_strDirs[g_numDirs] ); - path_add_slash( g_strDirs[g_numDirs] ); - g_numDirs++; + // clean and store copy to be safe of original's reallocation + const CopiedString pathCleaned = g_strDirs.emplace_back( StringOutputStream( 256 )( DirectoryCleaned( path ) ) ); if ( g_bUsePak ) { dir = g_dir_open( path, 0, NULL ); @@ -181,29 +189,16 @@ void vfsInitDirectory( const char *path ){ const char* name; while ( ( name = g_dir_read_name( dir ) ) ) { - for ( j = 0; j < g_numForbiddenDirs; ++j ) - { - if ( matchpattern( path_get_filename_start( name ), g_strForbiddenDirs[j], TRUE ) ) { - break; - } - } - if ( j < g_numForbiddenDirs ) { + if ( path_is_forbidden( name ) ) continue; - } const char *ext = path_get_filename_base_end( name ); if ( striEqual( ext, ".pk3" ) ) { - paks.push_back( StringOutputStream( 256 )( path, '/', name ) ); + paks.push_back( StringOutputStream( 256 )( pathCleaned.c_str(), name ) ); } else if ( striEqual( ext, ".pk3dir" ) ) { - if ( g_numDirs == VFS_MAXDIRS ) { - continue; - } - snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s/%s", path, name ); - FixDOSName( g_strDirs[g_numDirs] ); - path_add_slash( g_strDirs[g_numDirs] ); - ++g_numDirs; + g_strDirs.emplace_back( StringOutputStream( 256 )( pathCleaned.c_str(), name, '/' ) ); } } g_dir_close( dir ); @@ -233,8 +228,8 @@ std::vector vfsListShaderFiles( const char *shaderPath ){ list.emplace_back( name ); }; /* search in dirs */ - for ( int i = 0; i < g_numDirs; i++ ){ - GDir *dir = g_dir_open( StringOutputStream( 256 )( g_strDirs[ i ], shaderPath, "/" ), 0, NULL ); + for ( const auto& strdir : g_strDirs ){ + GDir *dir = g_dir_open( StringOutputStream( 256 )( strdir.c_str(), shaderPath, "/" ), 0, NULL ); if ( dir != NULL ) { const char* name; @@ -268,7 +263,7 @@ void vfsShutdown(){ // return the number of files that match int vfsGetFileCount( const char *filename ){ - int i, count = 0; + int count = 0; char fixed[NAME_MAX], tmp[NAME_MAX]; strcpy( fixed, filename ); @@ -282,9 +277,9 @@ int vfsGetFileCount( const char *filename ){ } } - for ( i = 0; i < g_numDirs; i++ ) + for ( const auto& dir : g_strDirs ) { - strcpy( tmp, g_strDirs[i] ); + strcpy( tmp, dir.c_str() ); strcat( tmp, fixed ); if ( access( tmp, R_OK ) == 0 ) { count++; @@ -296,7 +291,7 @@ int vfsGetFileCount( const char *filename ){ // NOTE: when loading a file, you have to allocate one extra byte and set it to \0 int vfsLoadFile( const char *filename, void **bufferptr, int index ){ - int i, count = 0; + int count = 0; char tmp[NAME_MAX], fixed[NAME_MAX]; // filename is a full path @@ -331,9 +326,9 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){ FixDOSName( fixed ); strLower( fixed ); - for ( i = 0; i < g_numDirs; i++ ) + for ( const auto& dir : g_strDirs ) { - strcpy( tmp, g_strDirs[i] ); + strcpy( tmp, dir.c_str() ); strcat( tmp, filename ); if ( access( tmp, R_OK ) == 0 ) { if ( count == index ) { @@ -386,9 +381,9 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){ // we need to end the buffer with a 0 ( (char*) ( *bufferptr ) )[file.size] = 0; - i = unzReadCurrentFile( zipfile, *bufferptr, file.size ); + const int size = unzReadCurrentFile( zipfile, *bufferptr, file.size ); unzCloseCurrentFile( zipfile ); - if ( i < 0 ) { + if ( size < 0 ) { return -1; } else{ @@ -406,7 +401,6 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){ bool vfsPackFile( const char *filename, const char *packname, const int compLevel ){ - int i; char tmp[NAME_MAX], fixed[NAME_MAX]; byte *bufferptr = NULL; @@ -414,9 +408,9 @@ bool vfsPackFile( const char *filename, const char *packname, const int compLeve FixDOSName( fixed ); strLower( fixed ); - for ( i = 0; i < g_numDirs; i++ ) + for ( const auto& dir : g_strDirs ) { - strcpy( tmp, g_strDirs[i] ); + strcpy( tmp, dir.c_str() ); strcat( tmp, filename ); if ( access( tmp, R_OK ) == 0 ) { if ( access( packname, R_OK ) == 0 ) { @@ -468,14 +462,14 @@ bool vfsPackFile( const char *filename, const char *packname, const int compLeve // we need to end the buffer with a 0 bufferptr[file.size] = 0; - i = unzReadCurrentFile( zipfile, bufferptr, file.size ); + const int size = unzReadCurrentFile( zipfile, bufferptr, file.size ); unzCloseCurrentFile( zipfile ); - if ( i < 0 ) { + if ( size < 0 ) { return false; } else{ mz_bool success = MZ_TRUE; - success &= mz_zip_add_mem_to_archive_file_in_place_with_time( packname, filename, bufferptr, i, 0, 0, compLevel, file.zipinfo.cur_file_info.dosDate ); + success &= mz_zip_add_mem_to_archive_file_in_place_with_time( packname, filename, bufferptr, size, 0, 0, compLevel, file.zipinfo.cur_file_info.dosDate ); if ( !success ){ Error( "Failed creating zip archive \"%s\"!\n", packname ); } diff --git a/tools/quake3/common/vfs.h b/tools/quake3/common/vfs.h index 3678d453..1387bc54 100644 --- a/tools/quake3/common/vfs.h +++ b/tools/quake3/common/vfs.h @@ -28,29 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _VFS_H_ -#define _VFS_H_ - -// to get PATH_MAX -#include -#if defined ( __linux__ ) || defined ( __APPLE__ ) -#include -#include -#include -#else -#include -#include - -#ifndef R_OK -#define R_OK 04 -#endif - -//#define S_ISDIR( mode ) ( mode & _S_IFDIR ) -#define PATH_MAX 260 -#endif -#include - -#define VFS_MAXDIRS 64 +#pragma once void vfsInitDirectory( const char *path ); void vfsShutdown(); @@ -60,8 +38,5 @@ std::vector vfsListShaderFiles( const char *shaderPath ); bool vfsPackFile( const char *filename, const char *packname, const int compLevel ); bool vfsPackFile_Absolute_Path( const char *filepath, const char *filename, const char *packname, const int compLevel ); -extern char g_strForbiddenDirs[VFS_MAXDIRS][PATH_MAX + 1]; -extern int g_numForbiddenDirs; +extern std::vector g_strForbiddenDirs; extern char g_strLoadedFileLocation[1024]; - -#endif // _VFS_H_ diff --git a/tools/quake3/q3data/md3lib.cpp b/tools/quake3/q3data/md3lib.cpp index 9f39eb5e..483bd0ed 100644 --- a/tools/quake3/q3data/md3lib.cpp +++ b/tools/quake3/q3data/md3lib.cpp @@ -22,6 +22,7 @@ #include "md3lib.h" #include "inout.h" #include "../common/cmdlib.h" +#include /* ** MD3_ComputeTagFromTri diff --git a/tools/quake3/q3data/p3dlib.cpp b/tools/quake3/q3data/p3dlib.cpp index cd76675c..27bc8fc5 100644 --- a/tools/quake3/q3data/p3dlib.cpp +++ b/tools/quake3/q3data/p3dlib.cpp @@ -27,6 +27,7 @@ #include "../common/cmdlib.h" #include "../common/qstringops.h" +#include "../common/qpathops.h" #define MAX_POLYSETS 64 diff --git a/tools/quake3/q3data/q3data.h b/tools/quake3/q3data/q3data.h index f5ca09a3..c4175548 100644 --- a/tools/quake3/q3data/q3data.h +++ b/tools/quake3/q3data/q3data.h @@ -31,6 +31,7 @@ #include "../common/cmdlib.h" #include "../common/inout.h" #include "../common/qstringops.h" +#include "../common/qpathops.h" #include "scriplib.h" #include "mathlib.h" #include "polyset.h" diff --git a/tools/quake3/q3data/video.cpp b/tools/quake3/q3data/video.cpp index 6a005bd0..4c63a8c1 100644 --- a/tools/quake3/q3data/video.cpp +++ b/tools/quake3/q3data/video.cpp @@ -20,6 +20,7 @@ */ #include +#include #include "q3data.h" static int s_resample_width = 256; @@ -39,6 +40,13 @@ static byte *s_soundtrack; static char s_base[32]; static char s_output_base[32]; +// for compression routines +typedef struct +{ + void *data; + int count, width, height; +} cblock_t; + /* =============================================================================== diff --git a/tools/quake3/q3map2/path_init.cpp b/tools/quake3/q3map2/path_init.cpp index aebeac9e..2d5567fd 100644 --- a/tools/quake3/q3map2/path_init.cpp +++ b/tools/quake3/q3map2/path_init.cpp @@ -401,11 +401,7 @@ void InitPaths( int *argc, char **argv ){ Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] ); } argv[ i - 1 ] = NULL; - if ( g_numForbiddenDirs < VFS_MAXDIRS ) { - strncpy( g_strForbiddenDirs[g_numForbiddenDirs], argv[i], PATH_MAX ); - g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = 0; - ++g_numForbiddenDirs; - } + g_strForbiddenDirs.emplace_back( argv[i] ); argv[ i ] = NULL; } diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index faec163c..d1d655ac 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -70,6 +70,7 @@ #include "cmdlib.h" #include "qstringops.h" +#include "qpathops.h" #include "md5lib.h" #include "ddslib.h"