diff --git a/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/Torque.rc b/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/Torque.rc new file mode 100644 index 000000000..cf88543da --- /dev/null +++ b/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/Torque.rc @@ -0,0 +1,85 @@ +//Microsoft Developer Studio generated resource script. +// +#define IDI_ICON1 103 +#define IDI_ICON2 107 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "torque.ico" +IDI_ICON2 ICON DISCARDABLE "torque.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/torque.ico b/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/torque.ico new file mode 100644 index 000000000..22ac1a3d1 Binary files /dev/null and b/Tools/dae2dts/buildFiles/VisualStudio 2005/projects/torque.ico differ diff --git a/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/Torque.rc b/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/Torque.rc new file mode 100644 index 000000000..cf88543da --- /dev/null +++ b/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/Torque.rc @@ -0,0 +1,85 @@ +//Microsoft Developer Studio generated resource script. +// +#define IDI_ICON1 103 +#define IDI_ICON2 107 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 108 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON DISCARDABLE "torque.ico" +IDI_ICON2 ICON DISCARDABLE "torque.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/torque.ico b/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/torque.ico new file mode 100644 index 000000000..22ac1a3d1 Binary files /dev/null and b/Tools/dae2dts/buildFiles/VisualStudio 2008/projects/torque.ico differ diff --git a/Tools/dae2dts/buildFiles/config/project.conf b/Tools/dae2dts/buildFiles/config/project.conf new file mode 100644 index 000000000..b78ca98f0 --- /dev/null +++ b/Tools/dae2dts/buildFiles/config/project.conf @@ -0,0 +1,13 @@ + diff --git a/Tools/dae2dts/buildFiles/config/projectCode.conf b/Tools/dae2dts/buildFiles/config/projectCode.conf new file mode 100644 index 000000000..57348ea8e --- /dev/null +++ b/Tools/dae2dts/buildFiles/config/projectCode.conf @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/Tools/dae2dts/game/readme.txt b/Tools/dae2dts/game/readme.txt new file mode 100644 index 000000000..4d0dcde89 --- /dev/null +++ b/Tools/dae2dts/game/readme.txt @@ -0,0 +1 @@ +Executable directory diff --git a/Tools/dae2dts/generateProjects.bat b/Tools/dae2dts/generateProjects.bat new file mode 100644 index 000000000..7c6ebd9d5 --- /dev/null +++ b/Tools/dae2dts/generateProjects.bat @@ -0,0 +1,13 @@ +@echo off + +SET TORQUEDIR=%2 + +IF NOT DEFINED TORQUEDIR SET TORQUEDIR=..\.. + +@%TORQUEDIR%\engine\bin\php\php %TORQUEDIR%\Tools\projectGenerator\projectGenerator.php buildFiles/config/project.conf %TORQUEDIR% +@echo ... +@echo ... +@echo ... +@echo REMEMBER: Restart Visual Studio if you are running it to be sure the new +@echo project file(s) are loaded! See docs for more info! +@IF X%1 == X pause \ No newline at end of file diff --git a/Tools/dae2dts/source/main.cpp b/Tools/dae2dts/source/main.cpp new file mode 100644 index 000000000..64a78c82e --- /dev/null +++ b/Tools/dae2dts/source/main.cpp @@ -0,0 +1,226 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include + +#include "platform/platform.h" +#include "platform/platformVolume.h" +#include "app/mainLoop.h" +#include "T3D/gameFunctions.h" +#include "core/stream/fileStream.h" +#include "core/resourceManager.h" +#include "ts/tsShape.h" +#include "ts/tsShapeConstruct.h" + +#ifdef TORQUE_OS_WIN32 +#include "platformWin32/platformWin32.h" +#include "platformWin32/winConsole.h" +#endif + + +extern TSShape* loadColladaShape( const Torque::Path &path ); + + +/** Print the usage string */ +void printUsage() +{ + Con::printf( +"DAE-2-DTS Converter v%s (c) GarageGames, LLC.\n\n" +"dae2dts [options] daeFilename\n\n" +"--config cfgFilename Set the conversion configuration filename.\n" +"--output dtsFilename Set the output DTS filename.\n" +"--dsq If set, all sequences in the shape will be saved\n" +" to DSQ files instead of being embedded in the DTS\n" +" file.\n" +"--dsq-only Same as --dsq, but no DTS file will be saved (handy for\n" +" animation only input files).\n" +"--compat If set, write to DTS v24 for compatibility with\n" +" ShowToolPro (no support for vertex colors, 2nd UV\n" +" set, autobillboards etc)\n" +"--diffuse If set, the diffuse texture will be used as the\n" +" material name (instead of the COLLADA name)\n" +"--materials If set, generate a materials.cs script in the output \n" +" folder to define Materials used in the shape.\n" +"--verbose If set, output progress information\n\n" +"Exits with zero on success, non-zero on failure\n\n", + TORQUE_APP_VERSION_STRING ); +} + +Torque::Path makeFullPath( const char* path ) +{ + char tempBuf[1024]; + Platform::makeFullPathName( path, tempBuf, sizeof(tempBuf), Platform::getCurrentDirectory() ); + return Torque::Path( String( tempBuf ) ); +} + +S32 TorqueMain( S32 argc, const char **argv ) +{ + S32 failed = 0; + + // Initialize the subsystems. + StandardMainLoop::init(); + Con::setVariable( "Con::Prompt", "" ); + WindowsConsole->enable( true ); + + // install all drives for now until we have everything using the volume stuff + Platform::FS::InstallFileSystems(); + Platform::FS::MountDefaults(); + + bool compatMode = false; + bool diffuseNames = false; + bool verbose = false; + bool saveDTS = true; + bool saveDSQ = false; + bool genMaterials = false; + Torque::Path cfgPath, srcPath, destPath; + + // Parse arguments + S32 i; + for ( i = 1; i < argc-1; i++ ) + { + if ( dStrEqual( argv[i], "--config" ) ) + cfgPath = makeFullPath( argv[++i] ); + else if ( dStrEqual( argv[i], "--output" ) ) + destPath = makeFullPath( argv[++i] ); + else if ( dStrEqual( argv[i], "--dsq" ) ) + saveDSQ = true; + else if ( dStrEqual( argv[i], "--dsq-only" ) ) + { + saveDTS = false; + saveDSQ = true; + } + else if ( dStrEqual( argv[i], "--compat" ) ) + compatMode = true; + else if ( dStrEqual( argv[i], "--diffuse" ) ) + diffuseNames = true; + else if ( dStrEqual( argv[i], "--materials" ) ) + genMaterials = true; + else if ( dStrEqual( argv[i], "--verbose" ) ) + verbose = true; + } + + if ( ( i >= argc ) || ( !dStrEndsWith(argv[i], ".dae") && !dStrEndsWith(argv[i], ".kmz" ) ) ) + { + Con::errorf( "Error: no DAE file specified.\n" ); + printUsage(); + return -1; + } + + srcPath = makeFullPath( argv[i] ); + if ( destPath.isEmpty() ) + { + destPath = srcPath; + destPath.setExtension( "dts" ); + } + + if ( !cfgPath.isEmpty() ) + Con::printf( "Configuration files not yet supported.\n" ); + + // Define script callbacks + if ( verbose ) + Con::evaluate( "function UpdateTSShapeLoadProgress(%progress, %msg) { echo(%msg); }" ); + else + Con::evaluate( "function UpdateTSShapeLoadProgress(%progress, %msg) { }" ); + + if ( verbose ) + Con::printf( "Parsing configuration file...\n" ); + + // Set import options + ColladaUtils::getOptions().reset(); + ColladaUtils::getOptions().forceUpdateMaterials = genMaterials; + ColladaUtils::getOptions().useDiffuseNames = diffuseNames; + + if ( verbose ) + Con::printf( "Reading dae file...\n" ); + + // Attempt to load the DAE file + Resource shape = ResourceManager::get().load( srcPath ); + if ( !shape ) + { + Con::errorf( "Failed to convert DAE file: %s\n", srcPath.getFullPath() ); + failed = 1; + } + else + { + if ( compatMode && !shape->canWriteOldFormat() ) + { + Con::errorf( "Warning: Attempting to save to DTS v24 but the shape " + "contains v26 features. Resulting DTS file may not be valid." ); + } + + FileStream outStream; + + if ( saveDSQ ) + { + Torque::Path dsqPath( destPath ); + dsqPath.setExtension( "dsq" ); + + for ( S32 i = 0; i < shape->sequences.size(); i++ ) + { + const String& seqName = shape->getName( shape->sequences[i].nameIndex ); + if ( verbose ) + Con::printf( "Writing DSQ file for sequence '%s'...\n", seqName.c_str() ); + + dsqPath.setFileName( destPath.getFileName() + "_" + seqName ); + + if ( outStream.open( dsqPath, Torque::FS::File::Write ) ) + { + shape->exportSequence( &outStream, shape->sequences[i], compatMode ); + outStream.close(); + } + else + { + Con::errorf( "Failed to save sequence to %s\n", dsqPath.getFullPath().c_str() ); + failed = 1; + } + } + } + if ( saveDTS ) + { + if ( verbose ) + Con::printf( "Writing DTS file...\n" ); + + if ( outStream.open( destPath, Torque::FS::File::Write ) ) + { + if ( saveDSQ ) + shape->sequences.setSize(0); + + shape->write( &outStream, compatMode ); + outStream.close(); + } + else + { + Con::errorf( "Failed to save shape to %s\n", destPath.getFullPath().c_str() ); + failed = 1; + } + } + } + + // Clean everything up. + StandardMainLoop::shutdown(); + + // Do we need to restart? + if( StandardMainLoop::requiresRestart() ) + Platform::restartInstance(); + + return failed; +} diff --git a/Tools/dae2dts/source/torqueConfig.h b/Tools/dae2dts/source/torqueConfig.h new file mode 100644 index 000000000..619c4c1f8 --- /dev/null +++ b/Tools/dae2dts/source/torqueConfig.h @@ -0,0 +1,214 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _TORQUECONFIG_H_ +#define _TORQUECONFIG_H_ + +//----------------------------------------------------------------------------- +//Hi, and welcome to the Torque Config file. +// +//This file is a central reference for the various configuration flags that +//you'll be using when controlling what sort of a Torque build you have. In +//general, the information here is global for your entire codebase, applying +//not only to your game proper, but also to all of your tools. + +/// Since we can build different engine "products" out of the same +/// base engine source we need a way to differentiate which product +/// this particular game is using. +/// +/// TGE 0001 +/// TGEA 0002 +/// TGB 0003 +/// TGEA 360 0004 +/// TGE WII 0005 +/// Torque 3D 0006 +/// +#define TORQUE_ENGINE_PRODUCT 0006 + +/// What's the name of your application? Used in a variety of places. +#define TORQUE_APP_NAME "dae2dts" + +/// What version of the application specific source code is this? +/// +/// Version number is major * 1000 + minor * 100 + revision * 10. +#define TORQUE_APP_VERSION 1000 + +/// Human readable application version string. +#define TORQUE_APP_VERSION_STRING "1.0.0" + +/// Define me if you want to enable multithreading support. +#ifndef TORQUE_MULTITHREAD +#define TORQUE_MULTITHREAD +#endif + +/// Define me if you want to disable Torque memory manager. +#ifndef TORQUE_DISABLE_MEMORY_MANAGER +#define TORQUE_DISABLE_MEMORY_MANAGER +#endif + +/// Define me if you don't want Torque to compile dso's +#define TORQUE_NO_DSO_GENERATION + +// Define me if this build is a tools build + +#ifndef TORQUE_PLAYER +# define TORQUE_TOOLS +#else +# undef TORQUE_TOOLS +#endif + +/// Define me if you want to enable the profiler. +/// See also the TORQUE_SHIPPING block below +//#define TORQUE_ENABLE_PROFILER + +/// Define me to enable debug mode; enables a great number of additional +/// sanity checks, as well as making AssertFatal and AssertWarn do something. +/// This is usually defined by the build target. +//#define TORQUE_DEBUG + +/// Define me if this is a shipping build; if defined I will instruct Torque +/// to batten down some hatches and generally be more "final game" oriented. +/// Notably this disables a liberal resource manager file searching, and +/// console help strings. +//#define TORQUE_SHIPPING + +/// Define me to enable a variety of network debugging aids. +/// +/// - NetConnection packet logging. +/// - DebugChecksum guards to detect mismatched pack/unpacks. +/// - Detection of invalid destination ghosts. +/// +//#define TORQUE_DEBUG_NET + +/// Define me to enable detailed console logging of net moves. +//#define TORQUE_DEBUG_NET_MOVES + +/// Enable this define to change the default Net::MaxPacketDataSize +/// Do this at your own risk since it has the potential to cause packets +/// to be split up by old routers and Torque does not have a mechanism to +/// stitch split packets back together. Using this define can be very useful +/// in controlled network hardware environments (like a LAN) or for singleplayer +/// games (like BArricade and its large paths) +//#define MAXPACKETSIZE 1500 + +/// Modify me to enable metric gathering code in the renderers. +/// +/// 0 does nothing; higher numbers enable higher levels of metric gathering. +//#define TORQUE_GATHER_METRICS 0 + +/// Define me if you want to enable debug guards in the memory manager. +/// +/// Debug guards are known values placed before and after every block of +/// allocated memory. They are checked periodically by Memory::validate(), +/// and if they are modified (indicating an access to memory the app doesn't +/// "own"), an error is flagged (ie, you'll see a crash in the memory +/// manager's validate code). Using this and a debugger, you can track down +/// memory corruption issues quickly. +//#define TORQUE_DEBUG_GUARD + +/// Define me if you want to enable instanced-static behavior +//#define TORQUE_ENABLE_THREAD_STATICS + +/// Define me if you want to gather static-usage metrics +//#define TORQUE_ENABLE_THREAD_STATIC_METRICS + +/// Define me if you want to enable debug guards on the FrameAllocator. +/// +/// This is similar to the above memory manager guards, but applies only to the +/// fast FrameAllocator temporary pool memory allocations. The guards are only +/// checked when the FrameAllocator frees memory (when it's water mark changes). +/// This is most useful for detecting buffer overruns when using FrameTemp<> . +/// A buffer overrun in the FrameAllocator is unlikely to cause a crash, but may +/// still result in unexpected behavior, if other FrameTemp's are stomped. +//#define FRAMEALLOCATOR_DEBUG_GUARD + +/// This #define is used by the FrameAllocator to set the size of the frame. +/// +/// It was previously set to 3MB but I've increased it to 16MB due to the +/// FrameAllocator being used as temporary storage for bitmaps in the D3D9 +/// texture manager. +#define TORQUE_FRAME_SIZE 16 << 20 + +// Finally, we define some dependent #defines. This enables some subsidiary +// functionality to get automatically turned on in certain configurations. + +#ifdef TORQUE_DEBUG + + #define TORQUE_GATHER_METRICS 0 + #define TORQUE_ENABLE_PROFILE_PATH + #ifndef TORQUE_DEBUG_GUARD + #define TORQUE_DEBUG_GUARD + #endif + #ifndef TORQUE_NET_STATS + #define TORQUE_NET_STATS + #endif + + // Enables the C++ assert macros AssertFatal, AssertWarn, etc. + #define TORQUE_ENABLE_ASSERTS + +#endif + +#ifdef TORQUE_RELEASE + // If it's not DEBUG, it's a RELEASE build, put appropriate things here. +#endif + +#ifdef TORQUE_SHIPPING + + // TORQUE_SHIPPING flags here. + +#else + + // Enable the profiler by default, if we're not doing a shipping build. + #define TORQUE_ENABLE_PROFILER + + // Enable the TorqueScript assert() instruction if not shipping. + #define TORQUE_ENABLE_SCRIPTASSERTS + + // We also enable GFX debug events for use in Pix and other graphics + // debugging tools. + #define TORQUE_ENABLE_GFXDEBUGEVENTS + +#endif + +#ifdef TORQUE_TOOLS +# define TORQUE_INSTANCE_EXCLUSION "TorqueToolsTest" +#else +# define TORQUE_INSTANCE_EXCLUSION "TorqueTest" +#endif + +// Someday, it might make sense to do some pragma magic here so we error +// on inconsistent flags. + +// The Xbox360 has it's own profiling tools, the Torque Profiler should not be used +#ifdef TORQUE_OS_XENON +# ifdef TORQUE_ENABLE_PROFILER +# undef TORQUE_ENABLE_PROFILER +# endif +# +# ifdef TORQUE_ENABLE_PROFILE_PATH +# undef TORQUE_ENABLE_PROFILE_PATH +#endif +#endif + + +#endif // _TORQUECONFIG_H_ + diff --git a/Tools/map2dif/map2dif_plus_tgea.exe b/Tools/map2dif/map2dif_plus_tgea.exe new file mode 100644 index 000000000..7db15c2e3 Binary files /dev/null and b/Tools/map2dif/map2dif_plus_tgea.exe differ diff --git a/Tools/projectGenerator/.gitignore b/Tools/projectGenerator/.gitignore new file mode 100644 index 000000000..db8dc6f67 --- /dev/null +++ b/Tools/projectGenerator/.gitignore @@ -0,0 +1,4 @@ +############# +## Torque +############# +templates_c/ diff --git a/Tools/projectGenerator/btargets/targets.inc b/Tools/projectGenerator/btargets/targets.inc new file mode 100644 index 000000000..248eba6d8 --- /dev/null +++ b/Tools/projectGenerator/btargets/targets.inc @@ -0,0 +1,217 @@ +setSolutionInfo( 'vc2k8_360_sln.tpl', '', '.sln' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'm', 'mm' ); + +$c->setPlatforms( "360" ); + +$c->setDontCompilePatterns( "#/platformPOSIX.*#", "#/platformMac.*#", "#/platformWin32.*#", "#\.mac\.#", "#\.win32\.#", "#/mac/#", "#/win32/#", "#\.mm$#", "#\.m$#" ); + +///////////////////////////// VS9 PS3 ///////////////////////////// + +$c = BuildTarget::add( 'VS9 PS3', // Name + 'buildFiles/VisualStudio 2008 (PS3)', // Solution output directory + 'projects/', // Project output directory (relative to solution) + '../../source/', // Base directory + 'vc2k8_ps3_proj.tpl', // App Project Template + 'vc2k8_ps3_proj.tpl', // Shared App Project Template + 'vc2k8_ps3_lib_proj.tpl', // Lib Project Template + 'vc2k8_ps3_dll_proj.tpl', // Shared Lib Project Template + '', // ActiveX Project Template (not supported on ps3) + '.vcproj' ); // File ext to write the project to + +// Solution template and extension +$c->setSolutionInfo( 'vc2k8_ps3_sln.tpl', '', '.sln' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'm', 'mm' ); + +$c->setPlatforms( "ps3" ); + +$c->setDontCompilePatterns( "#/platformXbox.*#", "#/platformWin32.*#", "#\.mac\.#", "#\.win\.#", "#\.win32\.#", "#/mac/#", "#/win32/#", "#\.mm$#", "#\.m$#" ); + + +///////////////////////////// VS9 ///////////////////////////// + +$c = BuildTarget::add( 'VS9', // Name + 'buildFiles/VisualStudio 2008', // Solution output directory + 'projects/', // Project output directory (relative to solution) + '../../source/', // Base directory + 'vc2k8_proj.tpl', // App Project Template + 'vc2k8_shared.tpl', // Shared App Project Template + 'vc2k8_lib_proj.tpl', // Lib Project Template + 'vc2k8_dll_proj.tpl', // Shared Lib Project Template + 'vc2k8_activex_proj.tpl', // ActiveX Control + '.vcproj' ); // File ext to write the project to + +// Solution template and extension +$c->setSolutionInfo( 'vc2k8_sln.tpl', 'vc2k8_proj_user.tpl', '.sln' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'asm', 'rc', 'm', 'mm', 'cs' ); + +$c->setPlatforms( "win", "win32" ); + +$c->setDotNetInfo('vc2k8_csproj.tpl'); + +$c->setDontCompilePatterns( "#/platformPOSIX.*#", "#/platformMac.*#", "#\.mac\.#", "#/mac/#", "#\.mm$#", "#\.m$#" ); + + +///////////////////////////// VS2010 ///////////////////////////// + +$c = BuildTarget::add( 'VS2010', // Name + 'buildFiles/VisualStudio 2010', // Solution output directory + 'projects/', // Project output directory (relative to solution) + '../../source/', // Base directory + 'vc2010_proj.tpl', // App Project Template + 'vc2010_shared.tpl', // Shared App Project Template + 'vc2010_lib_proj.tpl', // Lib Project Template + 'vc2010_dll_proj.tpl', // Shared Lib Project Template + 'vc2010_activex_proj.tpl', // ActiveX Control + '.vcxproj' ); // File ext to write the project to + +// Solution template and extension +$c->setSolutionInfo( 'vc2010_sln.tpl', '', '.sln', 'vc2010_filter.tpl' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'asm', 'rc', 'm', 'mm', 'cs' ); +$c->setSourceFileExtensions( 'c', 'cc', 'cpp' ); + +$c->setPlatforms( "win", "win32" ); + +$c->setDotNetInfo('vc2010_csproj.tpl'); + +$c->setDontCompilePatterns( "#/platformPOSIX.*#", "#/platformMac.*#", "#\.mac\.#", "#/mac/#", "#\.mm$#", "#\.m$#" ); + +/////////////////////////// XCode ///////////////////////////// + +$c = BuildTarget::add( 'Xcode', // Name + 'buildFiles/Xcode', // Solution output directory + '', // Project output directory (relative to solution) + '../../source/', // Base directory + 'xcode.tpl', // App Project Template + 'xcodeSharedApp.tpl', // Shared App Project Template + 'xcodeLib.tpl', // Lib Project Template + 'xcodeSharedLib.tpl', // Shared Lib Project Template + 'xcodeSafariPlugin.tpl', // Safari Plugin + '.xcodeproj/project.pbxproj' ); // File ext to write the project to + +$c->setDelimiters( '[', ']' ); // What delimeters does this template use? + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'm', 'mm' ); + +$c->setPlatforms( "mac" ); + +$c->setDontCompilePatterns( "*\.h*", "*win32*", "*\.win\.*", "#/platformWin32/#", "/D3D.*/", "*dsound*" ); + + +///////////////////////////// Make ////////////////////////////// + +$c = BuildTarget::add( 'Make', // Name + 'buildFiles/Make', // Solution Output directory + '', // Project Output directory (relative to solution) + '../../source/', // Base directory + 'makeApp.tpl', // App Project Template + 'makeAppShared.tpl', // Shared App Project Template + 'makeLib.tpl', // Lib Project Template + 'makeSo.tpl', // Shared Lib Project Template + '', // NP Plugin + '' ); // File ext to write the project to + +$c->setSolutionInfo( 'makeSolution.tpl', '', '' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'asm' ); + +$c->setPlatforms( "linux" ); + +$c->setDontCompilePatterns( "*\.h*", "*win32*", "*\.win\.*", "/D3D.*/", "*dsound*", "#/mac/#", "#\.mm$#", "#\.m$#", "*\.dedicated\.*" ); + + +///////////////////////////// Make Dedicated //////////////////// + +$c = BuildTarget::add( 'Make Dedicated', // Name + 'buildFiles/Make_Ded', // Output directory + '', // Project Output directory (relative to solution) + '../../source/', // Base directory + 'makeApp.tpl', // App Project Template + 'makeAppShared.tpl', // Shared App Project Template + 'makeLib.tpl', // Lib Project Template + 'makeSo.tpl', // Shared Lib Project Template + '', // NP Plugin + '' ); // File ext to write the project to + +$c->setSolutionInfo( 'makeSolution.tpl', '', '' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'asm' ); + +$c->setPlatforms( "linux_dedicated" ); + +$c->setDontCompilePatterns( "*\.h*", "*win32*", "*\.win\.*", "/D3D.*/", "#/gl/#", "#/mac/#", "#\.mm$#", "#\.m$#", "*\.client\.*" ); + + +///////////////////////////// Build ///////////////////////////// + +// 'buildManifest_'.$name.'_'.Generator::$platform.'.txt', + +$c = BuildTarget::add( 'build', // Name + 'buildFiles', // Solution output directory + 'projects/', // Project output directory (relative to solution) + '../source/', // Base directory + 'buildManifest.tpl', // App Project Template + 'buildManifest.tpl', // Shared Project Template + '', // Lib Project Template + '', // Shared Lib Project Template + '', // ActiveX Project Template + '.txt' ); + +$c->setFileExtensions( 'c', 'cc', 'h', 'cpp', 'inl', 'asm', 'm', 'mm' ); + +// NO PLATFORMS - SO ALL OR NONE? +$c->setPlatforms(""); + +//////////////////// + +function generateAppConfigOutputs( $name ) +{ + return BuildTarget::getInstances(); +} + +function generateLibConfigOutputs( $name ) +{ + return BuildTarget::getInstances(); +} + +?> diff --git a/Tools/projectGenerator/classes/ActiveXWebPlugin.php b/Tools/projectGenerator/classes/ActiveXWebPlugin.php new file mode 100644 index 000000000..1f8cabebf --- /dev/null +++ b/Tools/projectGenerator/classes/ActiveXWebPlugin.php @@ -0,0 +1,180 @@ +REGISTRY_APPID_RESOURCEID = ActiveXWebPlugin::generateUUID(); + //$this->WEBGAME_UUID = ActiveXWebPlugin::generateUUID(); + //$this->IWEBGAMECTRL_UUID = ActiveXWebPlugin::generateUUID(); + //$this->WEBGAMELIB_UUID = ActiveXWebPlugin::generateUUID(); + + $rootPhpBuildDir = getcwd(); + $this->FOLDER = $rootPhpBuildDir."\\web\\source\\activex\\"; + $this->GAMEFOLDER = $rootPhpBuildDir."\\game\\"; + + $this->PLUGIN_DLL = WebDeploymentWindows::$axPluginName.".dll"; + $this->PLUGIN_VERSION = WebDeploymentWindows::$version; + + + $this->REGISTRY_APPID_RESOURCEID = WebDeploymentWindows::$axAppUUID; + $this->WEBGAME_UUID = WebDeploymentWindows::$axWebGameUUID; + $this->IWEBGAMECTRL_UUID = WebDeploymentWindows::$axWebGameCtrlUUID; + $this->WEBGAMELIB_UUID = WebDeploymentWindows::$axWebGameLibUUID; + + + $this->WEBGAME_PLUGINNAME = str_replace(" ", "", WebDeploymentWindows::$axPluginName); + $this->WEBGAME_CTRLNAME = "IEWebGameCtrl";//str_replace(" ", "", WebDeploymentWindows::$axPluginName)."Ctrl"; + } + + function process($project) + { + $html = 'file://'.getcwd().'/game/web/sample.html'; + $html = str_replace("\\", "/", $html); + + // if the someone is clever enough to change the default location of IE, they are assumed to be + // clever enough to edit the debug command :) + + $IEExe = "C:\\Program Files\\Internet Explorer\\iexplore.exe"; + if (file_exists("C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe")) + $IEExe = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe"; + + $project->commandRelease = $IEExe; + $project->commandDebug = $IEExe; + $project->commandOptimized = $IEExe; + + $project->argsRelease = $html; + $project->argsDebug = $html; + $project->argsOptimized = $html; + + $this->processTemplates(); + } + + function readTemplate($filename) + { + $filename = realpath( dirname( $_SERVER[ 'PHP_SELF' ] ) ). "/templates/web/".$filename; + $fh = fopen($filename, 'r'); + $data = fread($fh, filesize($filename)); + fclose($fh); + return $data; + } + + function writeFile($filename, $data) + { + $filename = $this->FOLDER . $filename; + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function writeGameFile($filename, $data) + { + $filename = $this->GAMEFOLDER . $filename; + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function processTemplates() + { + // Make sure these come first so timestamp is oldest (for autogeneration) + $gen = $this->readTemplate("activex_IEWebGamePlugin_i_h.tpl"); + $this->writeFile("IEWebGamePlugin_i.h", $gen); + $gen = $this->readTemplate("activex_IEWebGamePlugin_i_c.tpl"); + $this->writeFile("IEWebGamePlugin_i.c", $gen); + + // WebGame.idl + $idl = $this->readTemplate("activex_IEWebGamePlugin_idl.tpl"); + $idl = str_replace("__WEBGAME_UUID__", $this->WEBGAME_UUID, $idl); + $idl = str_replace("__IWEBGAMECTRL_UUID__", $this->IWEBGAMECTRL_UUID, $idl); + $idl = str_replace("__WEBGAMELIB_UUID__", $this->WEBGAMELIB_UUID, $idl); + $idl = str_replace("__WEBGAME_PLUGINNAME__", $this->WEBGAME_PLUGINNAME, $idl); + $this->writeFile("IEWebGamePlugin.idl", $idl); + + // dllmain.h + $dllmain = $this->readTemplate("activex_dllmain_h.tpl"); + $dllmain = str_replace("__WEBGAME_PLUGINNAME__", $this->WEBGAME_PLUGINNAME, $dllmain); + $dllmain = str_replace("__REGISTRY_APPID_RESOURCEID__", $this->REGISTRY_APPID_RESOURCEID, $dllmain); + $this->writeFile("dllmain.h", $dllmain); + + //WebGameCtrl.rgs + $regs = $this->readTemplate("activex_IEWebGameCtrl_rgs.tpl"); + $regs = str_replace("__WEBGAME_UUID__", $this->WEBGAME_UUID, $regs); + $regs = str_replace("__WEBGAMELIB_UUID__", $this->WEBGAMELIB_UUID, $regs); + $regs = str_replace("__WEBGAME_PLUGINNAME__", $this->WEBGAME_PLUGINNAME, $regs); + $regs = str_replace("__WEBGAME_CTRLNAME__", $this->WEBGAME_CTRLNAME, $regs); + $this->writeFile("IEWebGameCtrl.rgs", $regs); + + //WebGamePlugin.rgs + $regs = $this->readTemplate("activex_IEWebGamePlugin_rgs.tpl"); + $regs = str_replace("__WEBGAME_PLUGINNAME__", $this->WEBGAME_PLUGINNAME, $regs); + $regs = str_replace("__WEBGAME_CTRLNAME__", $this->WEBGAME_CTRLNAME, $regs); + $this->writeFile("IEWebGamePlugin.rgs", $regs); + + + //WebGameCtrl.rc + $rc = $this->readTemplate("activex_IEWebGamePlugin_rc.tpl"); + $rc = str_replace("__PLUGIN_DLL__", $this->PLUGIN_DLL, $rc); + $rc = str_replace("__WEBGAME_PLUGINNAME__", $this->WEBGAME_PLUGINNAME, $rc); + + //versioning + + $rc = str_replace("__PLUGIN_VERSION_STRING__", $this->PLUGIN_VERSION, $rc); + $cd = str_replace(".", "," , $this->PLUGIN_VERSION); + $rc = str_replace("__PLUGIN_VERSION_COMMA_DELIMITED__", $cd, $rc); + + $this->writeFile("IEWebGamePlugin.rc", $rc); + + // handle the sample HTML (and whatever else) that is shared between plugins + WebPlugin::processActiveXPlugin($this); + + } + + static function generateUUID() + { + $command = realpath( dirname( $_SERVER[ 'PHP_SELF' ] ) )."\\..\\..\\Engine\\bin\\uuidgen\\uuidgen.exe -c"; + exec($command, $output); + return $output[0]; + } + +} + +?> diff --git a/Tools/projectGenerator/classes/BuildTarget.php b/Tools/projectGenerator/classes/BuildTarget.php new file mode 100644 index 000000000..8ab458f6c --- /dev/null +++ b/Tools/projectGenerator/classes/BuildTarget.php @@ -0,0 +1,208 @@ +name = $name; + $this->output_dir = $out; + $this->project_dir = $project; + $this->output_ext = $out_ext; + $this->base_dir = $base; + $this->template_app = $template_app; + $this->template_shared_app = $template_shared_app; + $this->template_lib = $template_lib; + $this->template_shared_lib = $template_shared_lib; + $this->template_activex = $template_activex; + $this->template_csproj = ""; + $this->template_user = ""; + + // The template for a filters file used by VS2010. + $this->template_filter = ""; + + $p = explode( '/', $project ); + $o = array(); + + for( $i = 0; $i < sizeof( $p ); $i++ ) + { + // Skip meaningless . or empty terms. + if( $p[ $i ] == '' || $p[ $i ] == '.' ) + continue; + + array_push( $o, '..' ); + } + + $this->project_rel_path = implode( '/', $o ); + + if (strlen($this->project_rel_path) > 0) + $this->project_rel_path = $this->project_rel_path . "/"; + } + + function setDelimiters( $l, $r ) + { + $this->ldelim = $l; + $this->rdelim = $r; + } + + function setSolutionInfo( $template_sln, $template_user, $output_ext, $template_filter = "" ) + { + $this->template_sln = $template_sln; + $this->solution_ext = $output_ext; + $this->template_user = $template_user; + $this->template_filter = $template_filter; + } + + function setDotNetInfo($template_csprog) + { + $this->template_csproj = $template_csprog; + } + + function setFileExtensions() + { + $args = func_get_args(); + $count = func_num_args(); + + $this->file_exts = $args; + } + + function setSourceFileExtensions() + { + $args = func_get_args(); + $count = func_num_args(); + + $this->source_file_exts = $args; + } + + function setRejectPatterns() + { + $args = func_get_args(); + + $this->reject_patterns = $args; + } + + function setDontCompilePatterns() + { + $args = func_get_args(); + + $this->dont_compile_patterns = $args; + } + + function setPlatforms() + { + $args = func_get_args(); + + $this->platforms = $args; + } + + function supportsPlatform( $platform ) + { + if( isset( $this->platforms ) ) + foreach( $this->platforms as $rule ) + if( strcmp( $rule, $platform ) == 0 ) + return true; + + return false; + } + + function ruleReject( $file ) + { + if( isset( $this->reject_patterns ) ) + foreach( $this->reject_patterns as $rule ) + if( preg_match( $rule, $file ) ) + return true; + + return false; + } + + function allowedFileExt( $file ) + { + foreach( $this->file_exts as $ext ) + { + $ext = ".{$ext}"; + $extLen = strlen( $ext ); + $possibleMatch = substr( $file, -$extLen, $extLen ); + + if( $possibleMatch == $ext ) + return true; + } + + return false; + } + + function isSourceFile( $file ) + { + foreach( $this->source_file_exts as $ext ) + { + $ext = ".{$ext}"; + $extLen = strlen( $ext ); + $possibleMatch = substr( $file, -$extLen, $extLen ); + if( $possibleMatch == $ext ) + return true; + } + + return false; + } +} + +?> diff --git a/Tools/projectGenerator/classes/FileUtil.php b/Tools/projectGenerator/classes/FileUtil.php new file mode 100644 index 000000000..3143453b5 --- /dev/null +++ b/Tools/projectGenerator/classes/FileUtil.php @@ -0,0 +1,133 @@ + 0 && $o[ sizeof( $o ) - 1 ] != '..' ) + { + array_pop( $o ); + + continue; + } + + array_push( $o, $p[ $i ] ); + } + + return implode( '/', $o ); + } + + // We apply some cleanup to the file list, specifically to remove + // any groupings with no siblings. + static function trimFileList( &$list ) + { + // Consider each child... + foreach( $list as $k => $v ) + { + // Only consider folders... + if( !is_array( $v ) ) + continue; + + // If child has only one child, then collapse it + reset( $v ); + + if( count( $v ) == 1 && is_array( current( $v ) ) ) + { + //echo("Trying to collapse $k\n"); + + $list[ $k ] = current( $v ); + + // Reset our walk through the list... + reset( $list ); + } + } + + // Now recurse on all children. + foreach( $list as $k => $v ) + { + // Only consider folders... + if( !is_array( $v ) ) + continue; + + FileUtil::trimFileList( &$list[ $k ] ); + } + } + + static function prepareOutputDir( $outdir ) + { + if( !file_exists( $outdir ) ) + { + echo( " Directory " . $outdir . " doesn't exist, attempting to create it.\n" ); + + if( !mkdir_r( $outdir, 0777 ) ) + { + echo( " Couldn't create directory.\n" ); + + return false; + } + } + + if( !chdir( $outdir ) ) + { + echo( "Couldn't change directory\n" ); + + return false;; + } + + return true; + } + + static function normalizeSlashes( $path ) + { + return str_replace( '\\', '/', $path ); + } + + static function isAbsolutePath( $path ) + { + // This looks complex, but its really fairly simple. + // + // We're detecting existing absolute paths in the include + // by converting it to absolute, normalizing the slashes, + // and comparing the results. + // + // If we get an absolute path we just don't prepend the + // project relative path part. + // + $orgPath = FileUtil::normalizeSlashes( $path ); + $absPath = FileUtil::normalizeSlashes( realpath( $path ) ); + return strcasecmp( $orgPath, $absPath ) == 0; + } +} +?> diff --git a/Tools/projectGenerator/classes/Generator.php b/Tools/projectGenerator/classes/Generator.php new file mode 100644 index 000000000..fde25460d --- /dev/null +++ b/Tools/projectGenerator/classes/Generator.php @@ -0,0 +1,612 @@ +isApp(); + } + + + static function getGeneratorLibsPath() + { + return self::$paths[ 'libs' ]; + } + + static function getGeneratorModulesPath() + { + return self::$paths['modules']; + } + + static function getEngineSrcDir() + { + return self::$paths['engineSrc']; + } + + static function getLibSrcDir() + { + return self::$paths['engineLib']; + } + + static function getEngineBinDir() + { + return self::$paths['engineBin']; + } + + static function addSrcDirRecursive($basePath, $dirPath) + { + $ignore = array( '.', '..', '.svn', '_svn', 'CVS' ); + $absPath = realpath($argv[1])."/buildFiles/"; + + array_push( self::$project_cur->dir_list, $basePath.'/'.$dirPath ); + + $dirHandle = opendir( $absPath.$basePath.'/'.$dirPath); + + while( $file = readdir( $dirHandle ) ) + { + if( !in_array( $file, $ignore ) ) + { + if( is_dir( $absPath.$basePath.'/'.$dirPath.'/'.$file ) ) + self::addSrcDirRecursive( $basePath, "$dirPath/$file"); + } + } + + closedir( $dirHandle ); + + } + + static function addSrcDir( $dir, $recurse = false ) + { + if (!$recurse) + array_push( self::$project_cur->dir_list, $dir ); + else + { + self::addSrcDirRecursive($dir, ""); + } + } + + static function addSrcFile( $file ) + { + array_push( self::$project_cur->dir_list, $file ); + } + + static function addIncludePath( $path ) + { + array_push( self::$project_cur->includes, $path ); + } + + static function addProjectDefine( $d, $v ) + { + if (!$v) + array_push( self::$project_cur->defines, $d ); + else + array_push( self::$project_cur->defines, $d."=".$v ); + } + + static function disableProjectWarning( $warning ) + { + array_push( self::$project_cur->disabledWarnings, $warning ); + } + + static function addProjectDefines( $args_array ) + { + self::$project_cur->defines = array_merge( self::$project_cur->defines, $args_array ); + } + + static function addProjectLibDir( $dir ) + { + array_push( self::$project_cur->lib_dirs, $dir ); + } + + static function addProjectLibInput( $lib ) + { + array_push( self::$project_cur->libs, $lib ); + } + + static function includeLib( $lib ) + { + foreach( self::$libGuard as $libName ) + if( $libName == $lib ) + return; + + array_push( self::$libGuard, $lib ); + + // if currently in a project, delay the include + if (Generator::inProjectConfig()) + { + array_push( self::$project_cur->lib_includes, $lib ); + return; + } + + // otherwise include it immediately + require( Generator::getGeneratorLibsPath() . $lib . '.conf' ); + } + + static function addProjectDependency( $pd ) + { + array_push( self::$project_cur->dependencies, $pd ); + } + + static function removeProjectDependency( $pd ) + { + foreach (self::$project_cur->dependencies as $key => $value) + { + if ($value == $pd) + { + unset(self::$project_cur->dependencies[$key]); + } + } + + self::$project_cur->dependencies = array_values(self::$project_cur->dependencies); + } + + + static function addProjectReference( $refName, $version = "") + { + self::$project_cur->addReference( $refName, $version ); + } + + static function setProjectGUID( $guid ) + { + self::$project_cur->guid = $guid; + } + + static function setProjectModuleDefinitionFile ( $mdef ) + { + self::$project_cur->moduleDefinitionFile = $mdef; + } + + static function beginModule( $name ) + { + if( !self::$module_cur ) + self::$module_cur = $name; + else + echo( "Generator::beginModule() - already in module!" ); + } + + static function endModule() + { + if( self::$module_cur ) + self::$module_cur = null; + else + trigger_error( "Generator::endModule() - no active module!", E_USER_ERROR ); + } + + static function inProjectConfig() + { + return self::$project_cur != null; + } + + static function setProjectSubSystem( $subSystem ) + { + self::$project_cur->setSubSystem( $subSystem ); + } + + static function beginProjectConfig( $name, $type, $guid, $game_dir, $output_name ) + { + if( !self::$project_cur ) + { + echo( " - begin project: " . $name . "=" . $guid . "\n" ); + + self::$project_cur = new Project( $name, $type, $guid, $game_dir, $output_name ); + + self::$config_projects[ $name ] = self::$project_cur; + } + else + trigger_error( "Generator::beginProjectConfig() - a project is already open!", E_USER_ERROR ); + } + + static function endProjectConfig( $type ) + { + //echo( "PT: " .$type. ":".self::$project_cur->type . "\n"); + + if( self::$project_cur ) + { + if( self::$project_cur->type == $type ) + { + echo( " - end project " . self::$project_cur->name . "\n" ); + + // Set project outputs + self::$project_cur->outputs = BuildTarget::getInstances(); + + // Allow project to optimize and validate state, etc + self::$project_cur->validate(); + + // Bit of flummery from original code, not sure what it is supposed to do -- neo + if( $type == Project::$TYPE_LIB ) + { + // Merge lib includes to global lib include array + self::$app_lib_includes = array_merge( self::$app_lib_includes, self::$project_cur->includes ); + } + else if ( $type == Project::$TYPE_SHARED_LIB ) + { + // Merge lib includes into app include list + self::$app_lib_includes = array_merge( self::$app_lib_includes, self::$project_cur->includes ); + } + else if ( $type == Project::$TYPE_ACTIVEX ) + { + // Merge lib includes into app include list + self::$app_lib_includes = array_merge( self::$app_lib_includes, self::$project_cur->includes ); + } + else if ( $type == Project::$TYPE_SAFARI ) + { + // Merge lib includes into app include list + self::$app_lib_includes = array_merge( self::$app_lib_includes, self::$project_cur->includes ); + } + else if ( $type == Project::$TYPE_SHARED_APP ) + { + // Merge lib includes into app include list + self::$app_lib_includes = array_merge( self::$app_lib_includes, self::$project_cur->includes ); + } + else if ( $type == Project::$TYPE_APP ) + { + // Merge lib includes into app include list + self::$project_cur->addIncludes( self::$app_lib_includes ); + } + + // Clear out sucker + $p = self::$project_cur; + self::$project_cur = null; + + // Now include any libraries included in the modules + foreach( $p->lib_includes as $libName ) + require( Generator::getGeneratorLibsPath() . $libName . '.conf' ); + + } + else + trigger_error( "Generator::endProjectConfig() - closing type mismatch!", E_USER_ERROR ); + } + else + trigger_error( "Generator::endProjectConfig() - no currently open project!", E_USER_ERROR ); + } + + static function beginActiveXConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_ACTIVEX, $guid, $game_dir, $output_name ); + + // Handle ActiveX specific setup (including ATL template processing, etc) + $activex = new ActiveXWebPlugin(); + $activex->process(self::$project_cur); + } + + static function endActiveXConfig() + { + self::endProjectConfig( Project::$TYPE_ACTIVEX ); + } + + static function beginSafariConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_SAFARI, $guid, $game_dir, $output_name ); + + // Handle Safari specific setup + $safari = new SafariWebPlugin(); + $safari->process(self::$project_cur); + } + + static function endSafariConfig() + { + self::endProjectConfig( Project::$TYPE_SAFARI ); + } + + + static function beginNPPluginConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_SHARED_LIB, $guid, $game_dir, $output_name ); + self::$project_cur->setUniformOutputFile(); + + // Handle NP specific setup (resource template processing, etc) + $NP = new NPWebPlugin(); + $NP->process(self::$project_cur); + } + + static function endNPPluginConfig() + { + self::endProjectConfig( Project::$TYPE_SHARED_LIB ); + } + + + static function beginSharedLibConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_SHARED_LIB, $guid, $game_dir, $output_name ); + } + + static function endSharedLibConfig() + { + self::endProjectConfig( Project::$TYPE_SHARED_LIB ); + } + + static function beginCSProjectConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_CSPROJECT, $guid, $game_dir, $output_name ); + } + + static function endCSProjectConfig() + { + self::endProjectConfig( Project::$TYPE_CSPROJECT ); + } + + + static function beginLibConfig( $lib_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $lib_name, Project::$TYPE_LIB, $guid, $game_dir, $output_name ); + } + + static function endLibConfig() + { + self::endProjectConfig( Project::$TYPE_LIB ); + } + + static function beginSharedAppConfig( $app_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $app_name, Project::$TYPE_SHARED_APP, $guid, $game_dir, $output_name ); + } + + static function endSharedAppConfig() + { + self::endProjectConfig( Project::$TYPE_SHARED_APP); + } + + + static function beginAppConfig( $app_name, $guid = '', $game_dir = 'game', $output_name = '' ) + { + self::beginProjectConfig( $app_name, Project::$TYPE_APP, $guid, $game_dir, $output_name ); + } + + static function endAppConfig() + { + self::endProjectConfig( Project::$TYPE_APP ); + } + + static function lookupProjectByName( $pname ) + { + foreach( self::$config_projects as $projName => $proj ) + if( $projName == $pname ) + return $proj; + + return null; + } + + // We encapsulate the meat of the project generator in generateProjects() + // so that more complex .config files can generate more than one run of projects + // without having to run a second instance of php + static function generateProjects( $tpl ) + { + // Alright, for each project scan and generate the file list. + $projectFiles = array (); + $rootPhpBuildDir = getcwd(); + + foreach( self::$config_projects as $projName => $proj ) + { + echo( " - Processing project '$projName'...\n" ); + + $proj->generate( $tpl, self::$platform, $rootPhpBuildDir ); + } + + echo( "PROJECTS DONE\n\n" ); + + chdir( $rootPhpBuildDir ); + } + + /////////////////////// SOLUTIONS ///////////////////////// + + static function beginSolution( $name, $guid ) + { + if( !self::$solution_cur ) + { + self::$solution_cur = new Solution( $name, $guid ); + self::$solutions[ $name ] = self::$solution_cur; + } + else + trigger_error( "Generator::beginSolution() - tried to start $name but already in the ".self::$solution_cur->name." solution!", E_USER_ERROR ); + } + + static function addSolutionProjectRef( $pname ) + { + if( isset( self::$solution_cur ) ) + self::$solution_cur->addProjectRef( $pname ); + else + trigger_error( "Generator::addSolutionProjectRef(): no such project - " . $pname . "\n", E_USER_ERROR ); + } + + static function addSolutionProjectRefExt( $pname, $ppath, $pguid ) + { + if( isset( self::$solution_cur ) ) + self::$solution_cur->addSolutionProjectRefExt( $pname, $ppath, $pguid ); + else + trigger_error( "Generator::addSolutionProjectRefExt(): no such project - " . $pname . "\n", E_USER_ERROR ); + } + + static function endSolution() + { + if( isset( self::$solution_cur ) ) + { + self::$solution_cur->setOutputs( BuildTarget::getInstances() ); + + self::$solution_cur = null; + } + else + trigger_error( "Generator::endSolution(): no active solution!\n", E_USER_ERROR ); + } + + static function generateSolutions( $tpl ) + { + echo( "GENERATING SOLUTIONS\n\n" ); + + $rootPhpBuildDir = getcwd(); + + // Process all solutions + foreach( self::$solutions as $sname => $solution ) + { + echo( " - Generating solution: " . $sname . "\n" ); + + chdir( $rootPhpBuildDir ); + + $solution->generate( $tpl, self::$platform, $rootPhpBuildDir ); + } + + chdir( $rootPhpBuildDir ); + } + + static function setDLLRuntime( $val ) + { + self::$useDLLRuntime = $val; + } +} +?> diff --git a/Tools/projectGenerator/classes/NPWebPlugin.php b/Tools/projectGenerator/classes/NPWebPlugin.php new file mode 100644 index 000000000..ab01cf68b --- /dev/null +++ b/Tools/projectGenerator/classes/NPWebPlugin.php @@ -0,0 +1,182 @@ +FOLDER = $rootPhpBuildDir."\\web\\source\\npplugin\\windows\\"; + $this->GAMEFOLDER = $rootPhpBuildDir."\\game\\"; + + $this->PLUGINNAME = WebDeploymentWindows::$npPluginName; + + $this->COMPANY = WebDeploymentWindows::$company; + $this->COMPANYKEY = WebDeploymentWindows::$companyKey; + $this->PLUGIN = WebDeploymentWindows::$plugin; + $this->PRODUCTNAME = WebDeploymentWindows::$productName; + $this->VERSION = WebDeploymentWindows::$version; + $this->MIMETYPE = WebDeploymentWindows::$mimeType; + $this->DESCRIPTION = WebDeploymentWindows::$description." ".$this->VERSION; + } + + function process($project) + { + $windowsRegistry = new WindowsRegistry(); + + $MozillaVersion = $windowsRegistry->ReadValue('HKEY_LOCAL_MACHINE\\SOFTWARE\\Mozilla\\Mozilla Firefox', 'CurrentVersion', TRUE); + $MozillaExe = $windowsRegistry->ReadValue('HKEY_LOCAL_MACHINE\\SOFTWARE\\Mozilla\\Mozilla Firefox\\'.$MozillaVersion.'\\Main', 'PathToExe', TRUE); + + // FireFox registry settings + $MozillaKey = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\MozillaPlugins\\@'; + + $html = 'file://'.getcwd().'/game/web/sample.html'; + $html = str_replace("\\", "/", $html); + $html = str_replace(" ", "%20", $html); + + $project->commandRelease = $MozillaExe; + $project->commandDebug = $MozillaExe; + $project->commandOptimized = $MozillaExe; + + $project->argsRelease = $html; + $project->argsDebug = $html; + $project->argsOptimized = $html; + + //$windowsRegistry->WriteValue($MozillaKey.$this->COMPANYKEY.'/'.$this->PLUGIN, 'Path', $this->GAMEFOLDER.$this->PLUGINNAME.'.dll'); + //$windowsRegistry->WriteValue($MozillaKey.$this->COMPANYKEY.'/'.$this->PLUGIN, 'ProductName', $this->PRODUCTNAME); + //$windowsRegistry->WriteValue($MozillaKey.$this->COMPANYKEY.'/'.$this->PLUGIN, 'Vendor', $this->COMPANY); + //$windowsRegistry->WriteValue($MozillaKey.$this->COMPANYKEY.'/'.$this->PLUGIN, 'Version', $this->VERSION); + //$windowsRegistry->WriteValue($MozillaKey.$this->COMPANYKEY.'/'.$this->PLUGIN.'\\MimeTypes\\application/'.$this->MIMETYPE, 'Description', $this->DESCRIPTION); + + unset($windowsRegistry); + + $this->processTemplates(); + + setProjectModuleDefinitionFile('../../../web/source/npplugin/windows/npWebGamePlugin.def'); + + /// Prefs + addProjectDefine( 'TORQUE_SHADERGEN' ); + addProjectDefine( 'TORQUE_SHARED' ); + addProjectDefine( 'TORQUE_WEBDEPLOY' ); + + // Firefox + addProjectDefine( 'FIREFOXPLUGIN_EXPORTS' ); + addProjectDefine( 'MOZILLA_STRICT_API' ); + addProjectDefine( 'XP_WIN' ); + + addProjectDefine( 'WIN32' ); + addProjectDefine( '_WINDOWS' ); + addProjectDefine( '_USRDLL' ); + + addSrcDir( '../web/source/common' ); + addSrcDir( '../web/source/npplugin' ); + addSrcDir( '../web/source/npplugin/windows' ); + + // Additional includes + addIncludePath( "../../web/source/npplugin/windows" ); + + addProjectLibDir( getAppLibSrcDir() . 'SDL/win32' ); + addProjectLibDir( getAppLibSrcDir() . 'unicode' ); + // addProjectLibDir( getAppLibSrcDir() . 'mozilla/lib' ); + + addProjectLibInput('COMCTL32.LIB'); + addProjectLibInput('COMDLG32.LIB'); + addProjectLibInput('USER32.LIB'); + addProjectLibInput('ADVAPI32.LIB'); + addProjectLibInput('GDI32.LIB'); + addProjectLibInput('WINMM.LIB'); + addProjectLibInput('WSOCK32.LIB'); + addProjectLibInput('vfw32.lib'); + addProjectLibInput('Imm32.lib'); + addProjectLibInput('UnicoWS.lib'); + addProjectLibInput('opengl32.lib'); + addProjectLibInput('glu32.lib'); + addProjectLibInput('ole32.lib'); + addProjectLibInput('shell32.lib'); + addProjectLibInput('oleaut32.lib'); + addProjectLibInput('version.lib'); + + } + + function readTemplate($filename) + { + $filename = realpath( dirname( $_SERVER[ 'PHP_SELF' ] ) ). "/templates/web/".$filename; + $fh = fopen($filename, 'r'); + $data = fread($fh, filesize($filename)); + fclose($fh); + return $data; + } + + function writeFile($filename, $data) + { + $filename = $this->FOLDER . $filename; + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function writeGameFile($filename, $data) + { + $filename = $this->GAMEFOLDER . $filename; + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function processTemplates() + { + + $data = $this->readTemplate("firefox_rc.tpl"); + $cd = str_replace(".", "," , $this->VERSION); + $data = str_replace("__PRODUCTVERSION__", $cd, $data); + $data = str_replace("__FILEDESCRIPTION__", $this->DESCRIPTION, $data); + $data = str_replace("__INTERNALNAME__", $this->PRODUCTNAME, $data); + $data = str_replace("__MIMETYPE__", "application/".$this->MIMETYPE, $data); + $data = str_replace("__ORIGINALFILENAME__", $this->PLUGINNAME.'.dll', $data); + $data = str_replace("__PRODUCTNAME__", $this->PRODUCTNAME, $data); + $data = str_replace("__COMPANY__", $this->COMPANY, $data); + $data = str_replace("__COMPANYKEY__", $this->COMPANYKEY, $data); + $data = str_replace("__PLUGIN__", $this->PLUGIN, $data); + $this->writeFile('NPWebGamePlugin.rc', $data); + + // handle the sample HTML (and whatever else) that is shared between plugins + WebPlugin::processNPPlugin($this); + + } + +} + +?> diff --git a/Tools/projectGenerator/classes/Project.php b/Tools/projectGenerator/classes/Project.php new file mode 100644 index 000000000..b155b67f6 --- /dev/null +++ b/Tools/projectGenerator/classes/Project.php @@ -0,0 +1,614 @@ +name = $name; + $this->outputName = $output_name; + $this->guid = $guid; + $this->type = $type; + $this->game_dir = $game_dir; + $this->dir_list = array(); + $this->defines = array(); + $this->includes = array(); + $this->libs = array(); + $this->lib_dirs = array(); + $this->lib_includes = array(); + $this->outputs = array(); + $this->dependencies = array(); + $this->disabledWarnings = array(); + $this->references = array(); + } + + public function isApp() + { + return $this->type == self::$TYPE_APP; + } + + public function isSharedApp() + { + return $this->type == self::$TYPE_SHARED_APP; + } + + public function isLib() + { + return $this->type == self::$TYPE_LIB; + } + + public function isSharedLib() + { + return $this->type == self::$TYPE_SHARED_LIB; + } + + public function isCSProject() + { + return $this->type == self::$TYPE_CSPROJECT; + } + + public function isActiveX() + { + return $this->type == self::$TYPE_ACTIVEX; + } + + public function isSafari() + { + return $this->type == self::$TYPE_SAFARI; + } + + public function setUniformOutputFile() + { + return $this->uniformOutputFile = 1; + } + + public function setSubSystem( $subSystem ) + { + $this->projSubSystem = $subSystem; + } + + public function validate() + { + // Sort the path list + sort( $this->dir_list ); + + // Make sure we don't have any duplicate paths + $this->dir_list = array_unique( $this->dir_list ); + } + + public function addReference($refName, $version = "") + { + $this->references[$refName] = $version; + } + + public function addIncludes( $includes ) + { + $this->includes = array_merge( $includes, $this->includes ); + } + + public function validateDependencies() + { + $pguids = array(); + + foreach( $this->dependencies as $pname ) + { + $p = Generator::lookupProjectByName( $pname ); + + if( $p ) + array_push( $pguids, $p->guid ); + else + trigger_error( "Project dependency not found: " .$pname, E_USER_ERROR ); + } + // todo: change to dependencyGuids + $this->dependencies = $pguids; + } + + private function generateXUID() + { + return sprintf( "%023X", Project::$xUID++ ); + } + + private function createFileEntry( $output, $curPath, $curFile ) + { + // See if we need to reject it based on our rules.. + if( $output->ruleReject( $curFile ) ) + return null; + + // Get the extension - is it one of our allowed values? + if( !$output->allowedFileExt( $curFile ) ) + return null; + + // Cool - note in the list! + $newEntry = new stdClass(); + $newEntry->name = $curFile; + $newEntry->path = FileUtil::collapsePath( $curPath . "/" . $curFile ); + + if ( !FileUtil::isAbsolutePath( $newEntry->path ) ) + { + // This could be consolidated into a single OR statement but it is easier to + // read as two separate if's + if ( !Generator::$absPath ) + $newEntry->path = $output->project_rel_path . $newEntry->path; + + if ( Generator::$absPath && !stristr($newEntry->path, Generator::$absPath) ) + $newEntry->path = $output->project_rel_path . $newEntry->path; + } + + // Store a project-unique ID here for Xcode projects + // It will be appended by a single char in the templates. + $newEntry->hash = Project::generateXUID(); + + return $newEntry; + } + + function generateFileList( &$projectFiles, $outputName, &$output ) + { + $projName = $this->name; + $projectFiles[ $projName ] = array(); + + foreach( $this->dir_list as $dir ) + { + $dir = FileUtil::normalizeSlashes( $dir ); + + // Build the path. + if ( FileUtil::isAbsolutePath( $dir ) ) + $curPath = $dir; + else + $curPath = FileUtil::collapsePath( $output->base_dir . $dir ); + $pathWalk = &$projectFiles[ $projName ]; + + if ( Generator::$absPath ) + { + if ( stristr($curPath, getEngineSrcDir()) || stristr($curPath, getLibSrcDir()) ) + $curPath = Generator::$absPath . "/". str_replace("../", "", $curPath); + } + + // Check if its a file or a directory. + // If its a file just add it directly and build a containng filter/folder structure, + // for it else if a dir add all files in it. + if( is_file( $curPath ) ) + { + // Get the file name + $curFile = basename( $curPath ); + $curPath = dirname( $curPath ); + + //echo( "FILE: " . $curFile . " PATH: " . $curPath . "\n" ); + } + + if( is_dir( $curPath ) ) + { + //echo( "DIR: " . $curPath . "\n" ); + + // Get the array we'll be adding things to... + $pathParts = explode( '/', FileUtil::collapsePath( $dir ) ); + + foreach( $pathParts as $part ) + { + // Skip parts that are relative paths - only want meaningful directories. + if( $part == '..' ) + continue; + + if( !is_array( $pathWalk[ $part ] ) ) + $pathWalk[ $part ] = array(); + + $pathWalk = &$pathWalk[ $part ]; + } + + // Open directory. + //echo( "SCANNING: " . $curPath . "\n"); + + $dirHdl = opendir( $curPath ); + + if( !$dirHdl ) + { + echo( "Path " . $curPath . " not found, giving up.\n" ); + + return false; + } + + // Iterate over all the files in the path if not a single file spec. + if( !$curFile ) + { + while( $curFile = readdir( $dirHdl ) ) + { + // Skip out if it's an uninteresting dir... + if( $curFile == '.' || $curFile == '..' || $curFile == '.svn' || $curFile == 'CVS' ) + continue; + + $newEntry = $this->createFileEntry( $output, $curPath, $curFile ); + + if( $newEntry ) + $pathWalk[] = $newEntry; + } + } + else + { + $newEntry = $this->createFileEntry( $output, $curPath, $curFile ); + + if( $newEntry ) + $pathWalk = $newEntry; + + $curFile = ''; + } + + // Clean up after ourselves! + closedir( $dirHdl ); + } + } + + FileUtil::trimFileList( &$projectFiles ); + + // Uncomment me to see the structure the file lister is returning. + //print_r($projectFiles); + + return true; + } + + private function setTemplateParams( $tpl, $output, &$projectFiles ) + { + // Set the template delimiters + $tpl->left_delimiter = $output->ldelim ? $output->ldelim : '{'; + $tpl->right_delimiter = $output->rdelim ? $output->rdelim : '}'; + + // Evaluate template into a file. + $tpl->assign_by_ref( 'projSettings', $this ); + $tpl->assign_by_ref( 'projOutput', $output ); + $tpl->assign_by_ref( 'fileArray', $projectFiles ); + $tpl->assign_by_ref( 'projName', $this->name ); + $tpl->assign_by_ref( 'projOutName', $this->outputName ); + $tpl->assign_by_ref( 'gameFolder', $this->game_dir ); + $tpl->assign_by_ref( 'GUID', $this->guid ); + $tpl->assign_by_ref( 'projDefines', $this->defines ); + $tpl->assign_by_ref( 'projDisabledWarnings', $this->disabledWarnings ); + $tpl->assign_by_ref( 'projIncludes', $this->includes ); + $tpl->assign_by_ref( 'projLibs', $this->libs ); + $tpl->assign_by_ref( 'projLibDirs', $this->lib_dirs ); + $tpl->assign_by_ref( 'projDepend', $this->dependencies ); + $tpl->assign_by_ref( 'gameProjectName', getGameProjectName() ); + $tpl->assign_by_ref( 'projModuleDefinitionFile', $this->moduleDefinitionFile ); + $tpl->assign_by_ref( 'projSubSystem', $this->projSubSystem ); + + if (Generator::$useDLLRuntime) + { + // /MD and /MDd + $tpl->assign( 'projRuntimeRelease', 2 ); + $tpl->assign( 'projRuntimeDebug', 3 ); + } + else + { + // /MT and /MTd + $tpl->assign( 'projRuntimeRelease', 0 ); + $tpl->assign( 'projRuntimeDebug', 1 ); + } + + if (!$this->commandDebug && ( $this->isSharedLib() || $this->isSharedApp() )) + { + + $command = "$(TargetDir)\\".$this->outputName; + $tpl->assign( 'commandDebug' , $command."_DEBUG.exe"); + $tpl->assign( 'commandRelease' , $command.".exe"); + $tpl->assign( 'commandOptimized' , $command."_OPTIMIZEDDEBUG.exe"); + } + else + { + $tpl->assign_by_ref( 'commandDebug' , $this->commandDebug); + $tpl->assign_by_ref( 'commandRelease' , $this->commandRelease); + $tpl->assign_by_ref( 'commandOptimized' , $this->commandOptimized); + } + + $tpl->assign_by_ref( 'argsDebug' , $this->argsDebug); + $tpl->assign_by_ref( 'argsRelease' , $this->argsRelease); + $tpl->assign_by_ref( 'argsOptimized' , $this->argsOptimized); + + $ptypes = array(); + $projectDepends = array(); + + foreach ($this->dependencies as $pname) + { + $p = Generator::lookupProjectByName( $pname ); + $projectDepends[$pname] = $p; + + if ( $p ) + $ptypes[$pname] = $p->isSharedLib() || $p->isSafari(); + } + + $tpl->assign_by_ref( 'projTypes', $ptypes ); + $tpl->assign_by_ref( 'projectDepends', $projectDepends ); + + // Assign some handy paths for the template to reference + $tpl->assign( 'projectOffset', $output->project_rel_path ); + + if ( Generator::$absPath ) + $tpl->assign( 'srcDir', Generator::$absPath . "/". str_replace("../", "", getAppEngineSrcDir()) ); + else + $tpl->assign( 'srcDir', $output->project_rel_path . getAppEngineSrcDir() ); + + if ( Generator::$absPath ) + $tpl->assign( 'libDir', Generator::$absPath . "/". str_replace("../", "", getAppLibSrcDir()) ); + else + $tpl->assign( 'libDir', $output->project_rel_path . getAppLibSrcDir() ); + + if ( Generator::$absPath ) + $tpl->assign( 'binDir', Generator::$absPath . "/". str_replace("../", "", getAppEngineBinDir()) ); + else + $tpl->assign( 'binDir', $output->project_rel_path . getAppEngineBinDir() ); + + $tpl->assign( 'uniformOutputFile', $this->uniformOutputFile); + } + + + private function conditionDirectories( $output, &$projectFiles ) + { + foreach ($this->includes as &$include) + { + if ( !FileUtil::isAbsolutePath( $include ) ) + $include = $output->project_rel_path . $include; + } + + foreach ($this->lib_dirs as &$libDirs) + { + if ( !FileUtil::isAbsolutePath( $libDirs ) ) + $libDirs = $output->project_rel_path . $libDirs; + } + + if ( Generator::$absPath ) + { + foreach ($this->includes as &$include) + { + if ( stristr($include, getEngineSrcDir()) || stristr($include, getLibSrcDir()) ) + $include = Generator::$absPath . "/". str_replace("../", "", $include); + } + + foreach ($this->lib_dirs as &$libDirs) + { + if ( stristr($libDirs, getEngineSrcDir()) || stristr($libDirs, getLibSrcDir()) ) + $libDirs = Generator::$absPath . "/". str_replace("../", "", $libDirs); + } + } + } + + public function generate( $tpl, $platform, $base_dir ) + { + // Alright, for each project scan and generate the file list. + $projectFiles = array (); + $rootPhpBuildDir = getcwd(); + + // Iterate over this project's outputs. + foreach( $this->outputs as $outputName => $output ) + { + $saved_includes = $this->includes; + $saved_lib_dirs = $this->lib_dirs; + + //print_r( $output ); + + // Supported platform? + if( !$output->supportsPlatform( $platform ) ) + { + //echo( " # Skipping output: '$outputName'.\n" ); + + continue; + } + + // Get to the right working directory (first go back to root, then to relative) + chdir( $base_dir ); + + //echo( " - Changing CWD to " . $output->output_dir . "\n" ); + // echo(" (From: " . getcwd() . ")\n"); + + if( !FileUtil::prepareOutputDir( $output->output_dir ) ) + continue; + + //echo( " - Scanning directory for output '.$outputName.'...\n" ); + + if( !$this->generateFileList( $projectFiles, $outputName, $output ) ) + { + echo( "File list generation failed. Giving up on this project.\n" ); + + continue; + } + + // Do any special work on the include/lib directories that we need + $this->conditionDirectories( $output, $projectFiles[ $this->name ] ); + + $this->projectFileExt = $output->output_ext; + + if ( $this->isCSProject() ) + $this->projectFileExt = ".csproj"; // always csproj C# project under VS/MonoDevelop + + $outfile = $output->project_dir . $this->name . $this->projectFileExt; + + echo( " o Writing project file " . $outfile . "\n" ); + + $this->setTemplateParams( $tpl, $output, $projectFiles[ $this->name ] ); + // To put a bandaid on the tools/player output dir problem + // CodeReview: This should be in the template. -- BJG, 3/13/2007 + // Moved into templates -- neo + + // Write file + $outdir = dirname( $outfile ); + + if( !file_exists( $outdir ) ) + mkdir_r( $outdir, 0777 ); + + if( $hdl = fopen( $outfile, 'w' ) ) + { + if ($this->isApp()) + $template = $output->template_app; + else if ($this->isLib()) + $template = $output->template_lib; + else if ($this->isSharedLib()) + $template = $output->template_shared_lib; + else if ($this->isSharedApp()) + $template = $output->template_shared_app; + else if ($this->isActiveX()) + $template = $output->template_activex; + else if ($this->isSafari()) + $template = $output->template_activex; //rename template? + else if ($this->isCSProject()) + $template = $output->template_csproj; + + fputs( $hdl, $tpl->fetch( $template ) ); + + fclose( $hdl ); + } + else + trigger_error( "Could not write output file: " . $output->outputFile, E_USER_ERROR ); + + if ($output->template_user) + { + + $outfile = $output->project_dir . $this->name . $this->projectFileExt .'.'.getenv("COMPUTERNAME").'.'.getenv("USERNAME").'.user'; + + if( !file_exists( $outfile ) ) + { + if( $hdl = fopen( $outfile, 'w' ) ) + { + $template = $output->template_user; + fputs( $hdl, $tpl->fetch( $template ) ); + fclose( $hdl ); + } + else + trigger_error( "Could not write output file: " . $outfile, E_USER_ERROR ); + } + + } + + // Build the .filters file used by VS2010. + if ( $output->template_filter ) + { + $filterData = new FilterData(); + array_walk( $projectFiles[ $this->name ], array($filterData, 'callback'), '' ); + + $tpl->assign_by_ref('Folders', $filterData->folders); + $tpl->assign_by_ref('SrcFiles', $filterData->srcFiles); + $tpl->assign_by_ref('IncFiles', $filterData->incFiles); + $tpl->assign_by_ref('OtherFiles', $filterData->otherFiles); + $tpl->register_function( 'gen_uuid', 'gen_uuid' ); + + $outfile = $output->project_dir . $this->name . $this->projectFileExt . '.filters'; + if ( $hdl = fopen( $outfile, 'w' ) ) + { + fputs( $hdl, $tpl->fetch( $output->template_filter ) ); + fclose( $hdl ); + } + } + + $this->includes = $saved_includes; + $this->lib_dirs = $saved_lib_dirs; + } + } +} + + +class FilterData +{ + public $folders = array(); + public $srcFiles = array(); + public $incFiles = array(); + public $otherFiles = array(); + + public function callback( $value, $key, $dir ) + { + if ( is_array( $value ) ) + { + if ( $dir != '' ) + $dirpath = $dir . '\\' . $key; + else + $dirpath = $key; + + array_push( $this->folders, $dirpath ); + array_walk( $value, array($this, 'callback'), $dirpath ); + return; + } + + $path = str_replace( '/', '\\', $value->path ); + + $ext = strrchr( $path, '.' ); + if ( $ext == FALSE ) + return; + + if ( strcasecmp( $ext, '.c' ) == 0 || + strcasecmp( $ext, '.cpp' ) == 0 || + strcasecmp( $ext, '.cc' ) == 0 ) + $this->srcFiles[$path] = $dir; + + else if ( strcasecmp( $ext, '.h' ) == 0 || + strcasecmp( $ext, '.hpp' ) == 0 || + strcasecmp( $ext, '.inl' ) == 0 ) + $this->incFiles[$path] = $dir; + + else + $this->otherFiles[$path] = $dir; + + } + +} // class FilterData + +?> diff --git a/Tools/projectGenerator/classes/SafariWebPlugin.php b/Tools/projectGenerator/classes/SafariWebPlugin.php new file mode 100644 index 000000000..6452d5200 --- /dev/null +++ b/Tools/projectGenerator/classes/SafariWebPlugin.php @@ -0,0 +1,111 @@ +FOLDER = $rootPhpBuildDir."/web/source/npplugin/mac/"; + $this->GAMEFOLDER = $rootPhpBuildDir."/game/"; + + $this->PLUGINNAME = WebDeploymentOSX::$safariPluginName; + $this->MIMETYPE = WebDeploymentOSX::$mimeType; + + $this->VERSION = WebDeploymentOSX::$version; + + $this->DESCRIPTION = WebDeploymentOSX::$description." ".$this->VERSION ; + + $this->BUNDLE = WebDeploymentOSX::$safariPluginName; + $this->IDENTIFIER = WebDeploymentOSX::$identifier; + } + + function process($project) + { + + $this->processTemplates(); + + + } + + function readTemplate($filename) + { + $filename = realpath( dirname( $_SERVER[ 'PHP_SELF' ] ) ). "/templates/web/".$filename; + $fh = fopen($filename, 'r'); + $data = fread($fh, filesize($filename)); + fclose($fh); + return $data; + } + + function writeFile($filename, $data) + { + $filename = $this->FOLDER . $filename; + + echo($filename); + + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function writeGameFile($filename, $data) + { + $filename = $this->GAMEFOLDER . $filename; + $fh = fopen($filename, 'w'); + fwrite($fh, $data); + fclose($fh); + } + + function processTemplates() + { + + $data = $this->readTemplate("safari_Info_plist.tpl"); + $data = str_replace("__CFBundleExecutable__", $this->BUNDLE, $data); + $data = str_replace("__CFBundleIdentifier__", $this->IDENTIFIER, $data); + $data = str_replace("__WebPluginDescription__", $this->DESCRIPTION, $data); + $data = str_replace("__WebPluginMIMEType__", "application/".$this->MIMETYPE, $data); + $data = str_replace("__WebPluginName__", $this->PLUGINNAME, $data); + + $data = str_replace("__GameName__", getGameProjectName(), $data); + + //TODO: handled by Toolbox + $data = str_replace("__GameInstallPath__", $this->GAMEFOLDER, $data); + + $this->writeFile('Info.plist', $data); + + WebPlugin::processNPPlugin($this); + } + +} + +?> diff --git a/Tools/projectGenerator/classes/Solution.php b/Tools/projectGenerator/classes/Solution.php new file mode 100644 index 000000000..ad352b9af --- /dev/null +++ b/Tools/projectGenerator/classes/Solution.php @@ -0,0 +1,159 @@ +name = $name; + $this->guid = $guid; + + $this->setOutputs( $outputs ); + } + + public function addProjectRef( $pname ) + { + array_push( $this->project_refs, $pname ); + } + + public function addSolutionProjectRefExt( $pname, $ppath, $pguid ) + { + $v = array(); + $v[0] = $ppath; + $v[1] = $pguid; + // This is the project GUID for a C# project + // TODO: Add support for C++ projects if need to add them + // as an external project, to date this hasn't been necessary + $v[2] = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"; + $this->project_extRefs[$pname] = $v; + } + + public function setOutputs( $outputs ) + { + if( isset( $outputs ) ) + $this->outputs = array_merge( $this->outputs, $outputs ); + } + + public function generate( $tpl, $platform, $root_dir ) + { + // Project container for templates + $projects = array(); + $refs = array(); + + // make sure that startup project is the first in the solution + + if (getGameProjectName()) + array_push( $refs, getGameProjectName() ); + + foreach( $this->project_refs as $pname ) + { + if (getGameProjectName() && $pname == getGameProjectName()) + continue; + + array_push( $refs, $pname ); + } + + // Look up each project ref and add its info to the list + foreach( $refs as $pname ) + { + $project = Generator::lookupProjectByName( $pname ); + + if( isset( $project ) ) + { + echo( " - project ref: " . $pname . " = " . $project->guid . "\n" ); + + array_push( $projects, $project ); + + // Let the project update any dependencies + $project->validateDependencies(); + } + else + trigger_error( "Solution::generate() - project ref not found: " . $pname . "\n", E_USER_ERROR ); + } + + // No use going forward if there were no projects for this solution is there? + // (Would we ever want to generate an empty solution at all?) + if( count( $projects ) == 0 ) + { + echo( "Solution::generate() - no project refs found for solution: " . $this->name . "\n" ); + + continue; + } + + // + //sort( $projects ); + + // Set smarty params that dont change during loop once here + $tpl->assign_by_ref( "solution_guid", $this->guid ); + $tpl->assign_by_ref( "projects", $projects ); + $tpl->assign_by_ref( "projectExtRefs", $this->project_extRefs ); + + // Generate a solution file for all outputs for this solution + foreach( $this->outputs as $output ) + { + // Supported platform? + if( !$output->supportsPlatform( $platform ) ) + { + //echo( " # Skipping output: '$outputName'.\n" ); + + continue; + } + + // Reset to base dir + chdir( $root_dir ); + + // Then offset + if( !FileUtil::prepareOutputDir( $output->output_dir ) || !$output->template_sln ) + continue; + + $outfile = $this->name . $output->solution_ext; + + echo( " - Writing solution file: " . $output->output_dir . "/" . $outfile ); + + // Project filenames are . where ext is set per output. + // The template builds each project output using the project name and this ext. + $tpl->assign_by_ref( "project_ext", $output->output_ext ); + + if( $f = fopen( $outfile, 'w' ) ) + { + fputs( $f, $tpl->fetch( $output->template_sln ) ); + + fclose( $f ); + + echo( " - success " . "\n" ); + } + else + trigger_error( "\nCould not write output file: " . $outfile, E_USER_ERROR ); + } + } +} +?> diff --git a/Tools/projectGenerator/classes/Torque3D.php b/Tools/projectGenerator/classes/Torque3D.php new file mode 100644 index 000000000..22b6e9004 --- /dev/null +++ b/Tools/projectGenerator/classes/Torque3D.php @@ -0,0 +1,267 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/classes/WebPlugin.php b/Tools/projectGenerator/classes/WebPlugin.php new file mode 100644 index 000000000..7b254d299 --- /dev/null +++ b/Tools/projectGenerator/classes/WebPlugin.php @@ -0,0 +1,85 @@ +MIMETYPE, self::$SAMPLE_HTML); + + } + + static function processActiveXPlugin($ax) + { + if (!self::$SAMPLE_HTML) + self::readTemplate(); + + $rootPhpBuildDir = getcwd(); + self::$GAME_FOLDER = $rootPhpBuildDir."/game/"; + + $projID = $ax->WEBGAME_PLUGINNAME.'.'.$ax->WEBGAME_CTRLNAME.'.'.'1'; + + self::$SAMPLE_HTML = str_replace("__PROJID__", $projID, self::$SAMPLE_HTML); + self::$SAMPLE_HTML = str_replace("__CLSID__", $ax->WEBGAMELIB_UUID, self::$SAMPLE_HTML); + + } + + static function writeSampleHtml() + { + // no plugins defined + if (!self::$SAMPLE_HTML) + return; + + $filename = self::$GAME_FOLDER . "web/sample.html"; + $fh = fopen($filename, 'w'); + fwrite($fh, self::$SAMPLE_HTML); + fclose($fh); + } +} + +?> diff --git a/Tools/projectGenerator/classes/WindowsRegistry.php b/Tools/projectGenerator/classes/WindowsRegistry.php new file mode 100644 index 000000000..731b4989b --- /dev/null +++ b/Tools/projectGenerator/classes/WindowsRegistry.php @@ -0,0 +1,453 @@ +WbemLocator = new COM('WbemScripting.SWbemLocator'); + $this->WbemServices = $this->WbemLocator->ConnectServer('.', '/root/default'); + $this->WbemServices->Security_->ImpersonationLevel = 0x3; + $this->RegObject = $this->WbemServices->Get('StdRegProv');*/ + + // Get the WMI StdRegProv class + try + { + $this->RegistryObject = new COM('WINMGMTS:{impersonationLevel=impersonate}!//./root/default:StdRegProv'); + } + catch (Exception $ex) + { + $this->RegistryObject = NULL; + throw new Exception('Could not get a connection to the registry.'); + } + } + + public function __destruct() + { + unset($this->RegistryObject); + } + + public function ReadValue($keyPath, $valueName, $asString = FALSE) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return NULL; + + $valueType = $this->GetValueType($hKeyId, $subKey, $valueName); + if (-1 == $valueType) + return NULL; + + switch ($valueType) + { + case self::REG_NONE: // No support for REG_NONE + return NULL; + case self::REG_SZ: + return $this->GetStringValue($hKeyId, $subKey, $valueName); + case self::REG_EXPAND_SZ: + return $this->GetExpandedStringValue($hKeyId, $subKey, $valueName); + case self::REG_BINARY: + return $this->GetBinaryValue($hKeyId, $subKey, $valueName, $asString); + case self::REG_DWORD: + return $this->GetDWORDValue($hKeyId, $subKey, $valueName, $asString); + case self::REG_MULTI_SZ: + return $this->GetMultiStringValue($hKeyId, $subKey, $valueName, $asString); + } + } + + public function WriteValue($keyPath, $valueName, $valueContents, $forceType = -1) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + if (!$this->CreateKey($keyPath)) + return FALSE; + + if (-1 != $forceType) + $valueType = $forceType; + else + $valueType = $this->GetValueType($hKeyId, $subKey, $valueName); + + if (self::REG_NONE == $valueType) // No support for REG_NONE + return FALSE; + + if (-1 == $valueType) // valueType unknown + { + if (is_string($valueContents)) + $valueType = self::REG_SZ; + else if (is_int($valueContents)) + $valueType = self::REG_DWORD; + else if (is_array($valueContents) && count($valueContents)) + { + if (is_string($valueContents[0])) + $valueType = self::REG_MULTI_SZ; + else if (is_int($valueContents[0])) + $valueType = self::REG_BINARY; + } + } + if (-1 == $valueType) // valueType still unknown, leave + return FALSE; + + $result = -1; + + if ((self::REG_SZ == $valueType) || (self::REG_EXPAND_SZ == $valueType)) + { + //if (!is_string($valueContents)) + // $valueContents = strval($valueContents); + + if (self::REG_SZ == $valueType) + $result = $this->RegistryObject->SetStringValue($hKeyId, $subKey, $valueName, $valueContents); + else + $result = $this->RegistryObject->SetExpandedStringValue($hKeyId, $subKey, $valueName, $valueContents); + } + else if (self::REG_DWORD == $valueType) + { + //if (!is_int($valueContents)) + // $valueContents = intval($valueContents); + + $result = $this->RegistryObject->SetDWORDValue($hKeyId, $subKey, $valueName, $valueContents); + } + else if (self::REG_MULTI_SZ == $valueType) + { + if (!is_array($valueContents) || !is_string($valueContents[0])) + return FALSE; + + $result = $this->RegistryObject->SetMultiStringValue($hKeyId, $subKey, $valueName, $valueContents); + } + else if (self::REG_BINARY == $valueType) + { + if (!is_array($valueContents) || !is_int($valueContents[0])) + return FALSE; + + $result = $this->RegistryObject->SetBinaryValue($hKeyId, $subKey, $valueName, $valueContents); + } + + return (0 == $result); + } + + public function DeleteValue($keyPath, $valueName) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + return ($this->RegistryObject->DeleteValue($hKeyId, $subKey, $valueName) == 0); + } + + public function GetValueNames($keyPath, $includeTypes = FALSE) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + $valueList = array(); + if (!$this->EnumValues($hKeyId, $subKey, $valueList)) + return NULL; + + if (!$includeTypes) + { + $valueNames = array(); + for ($i = 0, $cnt = count($valueList); $i < $cnt; $i++) + $valueNames[] = $valueList[$i][0]; + return $valueNames; + } + else + return $valueList; + } + + public function CreateKey($keyPath) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + return ($this->RegistryObject->CreateKey($hKeyId, $subKey) == 0); + } + + public function DeleteKey($keyPath, $deleteSubkeys = FALSE) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + if (!$deleteSubkeys) + return ($this->RegistryObject->DeleteKey($hKeyId, $subKey) == 0); + else + { + if (!function_exists('deleteSubKeysRecursive')) + { + function deleteSubKeysRecursive(&$thisRef, $hKeyId, $subKey) + { + $mapHkeysToString = array( + WindowsRegistry::HKEY_CLASSES_ROOT => 'HKEY_CLASSES_ROOT', + WindowsRegistry::HKEY_CURRENT_USER => 'HKEY_CURRENT_USER', + WindowsRegistry::HKEY_LOCAL_MACHINE => 'HKEY_LOCAL_MACHINE', + WindowsRegistry::HKEY_USERS => 'HKEY_USERS', + WindowsRegistry::HKEY_CURRENT_CONFIG => 'HKEY_CURRENT_CONFIG'); + + if (!isset($mapHkeysToString[$hKeyId])) + return FALSE; + + $subKeys = $thisRef->GetSubKeys($mapHkeysToString[$hKeyId] . '\\' . $subKey); + if ($subKeys) + { + for ($i = 0, $cnt = count($subKeys); $i < $cnt; $i++) + { + if (!deleteSubKeysRecursive($thisRef, $hKeyId, $subKey . '\\' . $subKeys[$i])) + return FALSE; + } + } + + return ($thisRef->DeleteKey($mapHkeysToString[$hKeyId] . '\\' . $subKey)); + } + } + + return deleteSubKeysRecursive($this, $hKeyId, $subKey); + } + } + + public function GetSubKeys($keyPath) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + $keyList = array(); + if (!$this->EnumKeys($hKeyId, $subKey, $keyList)) + return NULL; + + return $keyList; + } + + public function KeyExists($keyPath) + { + $hKeyId = 0; + $subKey = ''; + if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey)) + return FALSE; + + return ($this->RegistryObject->EnumValues($hKeyId, $subKey, new VARIANT(), new VARIANT()) == 0); + } + + // PRIVATE FUNCTIONS + // ================================ + private function SplitKeyPath($keyPath, &$hKeyIdResult, &$subKeyResult) + { + $hKeyIdResult = 0; + $subKeyResult = 'foo'; + + $splitPath = explode('\\', $keyPath, 2); + + if (FALSE === $splitPath) + return FALSE; + else if (count($splitPath) == 1) + $splitPath[1] = ''; + + $subKeyResult = $splitPath[1]; + + switch ($splitPath[0]) + { + case 'HKEY_CLASSES_ROOT': + $hKeyIdResult = self::HKEY_CLASSES_ROOT; + break; + case 'HKEY_CURRENT_USER': + $hKeyIdResult = self::HKEY_CURRENT_USER; + break; + case 'HKEY_LOCAL_MACHINE': + $hKeyIdResult = self::HKEY_LOCAL_MACHINE; + break; + case 'HKEY_USERS': + $hKeyIdResult = self::HKEY_USERS; + break; + case 'HKEY_CURRENT_CONFIG': + $hKeyIdResult = self::HKEY_CURRENT_CONFIG; + break; + default: + return FALSE; + } + + return TRUE; + } + + private function EnumKeys($hKeyId, $subKey, &$keyList) + { + $keyNames = new VARIANT(); + if ($this->RegistryObject->EnumKey($hKeyId, $subKey, $keyNames) != 0) + return FALSE; + + $keyList = array(); + + if (variant_get_type($keyNames) == (VT_VARIANT | VT_ARRAY)) + { + for ($i = 0, $cnt = count($keyNames); $i < $cnt; $i++) + $keyList[] = strval($keyNames[$i]); + } + + return TRUE; + } + + private function EnumValues($hKeyId, $subKey, &$valueList) + { + $valueNames = new VARIANT(); + $valueTypes = new VARIANT(); + + if ($this->RegistryObject->EnumValues($hKeyId, $subKey, $valueNames, $valueTypes) != 0) + return FALSE; + + $valueList = array(); + + if (variant_get_type($valueNames) == (VT_VARIANT | VT_ARRAY)) + { + for ($i = 0, $cnt = count($valueNames); $i < $cnt; $i++) + $valueList[] = array(strval($valueNames[$i]), intval($valueTypes[$i])); + } + else // Handle a bug in StdRegProv's EnumValues (http://groups.google.com/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/d74c0ca865887e6b) + { + if ($this->GetStringValue($hKeyId, $subKey, '') != NULL) + $valueList[] = array('', self::REG_SZ); + else if ($this->GetDWORDValue($hKeyId, $subKey, '') != NULL) + $valueList[] = array('', self::REG_DWORD); + else if ($this->GetExpandedStringValue($hKeyId, $subKey, '') != NULL) + $valueList[] = array('', self::REG_EXPAND_SZ); + else if ($this->GetBinaryValue($hKeyId, $subKey, '') != NULL) + $valueList[] = array('', self::REG_BINARY); + else if ($this->GetMultiStringValue($hKeyId, $subKey, '') != NULL) + $valueList[] = array('', self::REG_MULTI_SZ); + } + + return TRUE; + } + + private function GetValueType($hKeyId, $subKey, $valueName) + { + $valueList = array(); + if (!$this->EnumValues($hKeyId, $subKey, $valueList)) + return -1; + + for ($i = 0, $cnt = count($valueList); $i < $cnt; $i++) + { + if ($valueList[$i][0] == $valueName) + return $valueList[$i][1]; + } + + return -1; + } + + private function GetStringValue($hKeyId, $subKey, $valueName) + { + $stringValue = new VARIANT(); + return (($this->RegistryObject->GetStringValue($hKeyId, $subKey, $valueName, $stringValue) == 0) ? + strval($stringValue) : NULL); + } + + private function GetExpandedStringValue($hKeyId, $subKey, $valueName) + { + $expandStringValue = new VARIANT(); + return ((0 == $this->RegistryObject->GetExpandedStringValue($hKeyId, $subKey, $valueName, $expandStringValue)) ? + strval($expandStringValue) : NULL); + } + + private function GetBinaryValue($hKeyId, $subKey, $valueName, $asString = FALSE) + { + $binaryValue = new VARIANT(); + if ($this->RegistryObject->GetBinaryValue($hKeyId, $subKey, $valueName, $binaryValue) != 0) + return NULL; + + if ($asString) + { + $result = ''; + for ($i = 0, $cnt = count($binaryValue); $i < $cnt; $i++) + $result .= dechex($binaryValue[$i]) . ((($cnt - 1) != $i) ? ' ' : ''); + } + else + { + $result = array(); + for ($i = 0, $cnt = count($binaryValue); $i < $cnt; $i++) + $result .= intval($binaryValue[$i]); + } + + return $result; + } + + private function GetDWORDValue($hKeyId, $subKey, $valueName, $asString = FALSE) + { + $dwordValue = new VARIANT(); + return (($this->RegistryObject->GetDWORDValue($hKeyId, $subKey, $valueName, $dwordValue) == 0) ? + ($asString ? strval($dwordValue) : intval($dwordValue)) : NULL); + } + + private function GetMultiStringValue($hKeyId, $subKey, $valueName, $asString = FALSE) + { + $multiStringValue = new VARIANT(); + if ($this->RegistryObject->GetMultiStringValue($hKeyId, $subKey, $valueName, $multiStringValue) != 0) + return NULL; + + if ($asString) + { + $result = ''; + for ($i = 0, $cnt = count($multiStringValue); $i < $cnt; $i++) + $result .= strval($multiStringValue[$i]) . ((($cnt - 1) != $i) ? "\n" : ''); + } + else + { + $result = array(); + for ($i = 0, $cnt = count($multiStringValue); $i < $cnt; $i++) + $result[] = strval($multiStringValue[$i]); + } + + return $result; + } +} +?> \ No newline at end of file diff --git a/Tools/projectGenerator/classes/plist/CFBinaryPropertyList.php b/Tools/projectGenerator/classes/plist/CFBinaryPropertyList.php new file mode 100644 index 000000000..09290d920 --- /dev/null +++ b/Tools/projectGenerator/classes/plist/CFBinaryPropertyList.php @@ -0,0 +1,895 @@ + + * @author Christian Kruse + * @package plist + * @version $Id$ + */ + +/** + * Facility for reading and writing binary PropertyLists. Ported from {@link http://www.opensource.apple.com/source/CF/CF-476.15/CFBinaryPList.c CFBinaryPList.c}. + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @example example-read-02.php Read a Binary PropertyList + * @example example-read-03.php Read a PropertyList without knowing the type + */ +abstract class CFBinaryPropertyList { + /** + * Table containing uniqued objects + * @var array + */ + protected $uniqueTable = Array(); + + /** + * Number of objects in file + * @var integer + */ + protected $countObjects = 0; + + /** + * The length of all strings in the file (byte length, not character length) + * @var integer + */ + protected $stringSize = 0; + + /** + * The length of all ints in file (byte length) + * @var integer + */ + protected $intSize = 0; + + /** + * The length of misc objects (i.e. not integer and not string) in file + * @var integer + */ + protected $miscSize = 0; + + /** + * Number of object references in file (needed to calculate reference byte length) + * @var integer + */ + protected $objectRefs = 0; + + /** + * Number of objects written during save phase; needed to calculate the size of the object table + * @var integer + */ + protected $writtenObjectCount = 0; + + /** + * Table containing all objects in the file + */ + protected $objectTable = Array(); + + /** + * The size of object references + */ + protected $objectRefSize = 0; + + /** + * The „offsets” (i.e. the different entries) in the file + */ + protected $offsets = Array(); + + /** + * Read a „null type” (filler byte, true, false, 0 byte) + * @param $length The byte itself + * @return the byte value (e.g. CFBoolean(true), CFBoolean(false), 0 or 15) + * @throws PListException on encountering an unknown null type + */ + protected function readBinaryNullType($length) { + switch($length) { + case 0: return 0; // null type + case 8: return new CFBoolean(false); + case 9: return new CFBoolean(true); + case 15: return 15; // fill type + } + + throw new PListException("unknown null type: $length"); + } + + /** + * Create an 64 bit integer using bcmath or gmp + * @param int $hi The higher word + * @param int $lo The lower word + * @return mixed The integer (as int if possible, as string if not possible) + * @throws PListException if neither gmp nor bc available + */ + protected static function make64Int($hi,$lo) { + // on x64, we can just use int + if(PHP_INT_SIZE > 4) return (((int)$hi)<<32) | ((int)$lo); + + // lower word has to be unsigned since we don't use bitwise or, we use bcadd/gmp_add + $lo = sprintf("%u", $lo); + + // use GMP or bcmath if possible + if(function_exists("gmp_mul")) return gmp_strval(gmp_add(gmp_mul($hi, "4294967296"), $lo)); + + if(function_exists("bcmul")) return bcadd(bcmul($hi,"4294967296"), $lo); + + throw new PListException("either gmp or bc has to be installed!"); + } + + /** + * Read an integer value + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the integer value, coded as „set bit $length to 1” + * @return CFNumber The integer value + * @throws PListException if integer val is invalid + * @throws IOException if read error occurs + */ + protected function readBinaryInt($fname,$fd,$length) { + if($length > 3) throw new PListException("Integer greater than 8 bytes: $length"); + + $nbytes = 1 << $length; + + $val = null; + if(strlen($buff = fread($fd, $nbytes)) != $nbytes) throw IOException::readError($fname); + switch($length) { + case 0: + $val = unpack("C", $buff); + $val = $val[1]; + break; + case 1: + $val = unpack("n", $buff); + $val = $val[1]; + break; + case 2: + $val = unpack("N", $buff); + $val = $val[1]; + break; + case 3: + $words = unpack("Nhighword/Nlowword",$buff); + //$val = $words['highword'] << 32 | $words['lowword']; + $val = self::make64Int($words['highword'],$words['lowword']); + break; + } + + return new CFNumber($val); + } + + /** + * Read a real value + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the integer value, coded as „set bit $length to 1” + * @return CFNumber The real value + * @throws PListException if real val is invalid + * @throws IOException if read error occurs + */ + protected function readBinaryReal($fname,$fd,$length) { + if($length > 3) throw new PListException("Real greater than 8 bytes: $length"); + + $nbytes = 1 << $length; + $val = null; + if(strlen($buff = fread($fd, $nbytes)) != $nbytes) throw IOException::readError($fname); + + switch($length) { + case 0: // 1 byte float? must be an error + case 1: // 2 byte float? must be an error + $x = $length + 1; + throw new PListException("got {$x} byte float, must be an error!"); + case 2: + $val = unpack("f", strrev($buff)); + $val = $val[1]; + break; + case 3: + $val = unpack("d", strrev($buff)); + $val = $val[1]; + break; + } + + return new CFNumber($val); + } + + /** + * Read a date value + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the integer value, coded as „set bit $length to 1” + * @return CFDate The date value + * @throws PListException if date val is invalid + * @throws IOException if read error occurs + */ + protected function readBinaryDate($fname,$fd,$length) { + if($length > 3) throw new PListException("Date greater than 8 bytes: $length"); + + $nbytes = 1 << $length; + $val = null; + if(strlen($buff = fread($fd, $nbytes)) != $nbytes) throw IOException::readError($fname); + + switch($length) { + case 0: // 1 byte CFDate is an error + case 1: // 2 byte CFDate is an error + $x = $length + 1; + throw new PListException("{$x} byte CFdate, error"); + + case 2: + $val = unpack("f", strrev($buff)); + $val = $val[1]; + break; + case 3: + $val = unpack("d", strrev($buff)); + $val = $val[1]; + break; + } + + return new CFDate($val,CFDate::TIMESTAMP_APPLE); + } + + /** + * Read a data value + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the integer value, coded as „set bit $length to 1” + * @return CFData The data value + * @throws IOException if read error occurs + */ + protected function readBinaryData($fname,$fd,$length) { + if(strlen($buff = fread($fd, $length)) != $length) throw IOException::readError($fname); + return new CFData($buff,false); + } + + /** + * Read a string value, usually coded as utf8 + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the string value + * @return CFString The string value, utf8 encoded + * @throws IOException if read error occurs + */ + protected function readBinaryString($fname,$fd,$length) { + if(strlen($buff = fread($fd, $length)) != $length) throw IOException::readError($fname); + + if(!isset($this->uniqueTable[$buff])) $this->uniqueTable[$buff] = true; + return new CFString($buff); + } + + /** + * Convert the given string from one charset to another. + * Trying to use MBString, Iconv, Recode - in that particular order. + * @param string $string the string to convert + * @param string $fromCharset the charset the given string is currently encoded in + * @param string $toCharset the charset to convert to, defaults to UTF-8 + * @return string the converted string + * @throws PListException on neither MBString, Iconv, Recode being available + */ + public static function convertCharset($string, $fromCharset, $toCharset='UTF-8') { + if(function_exists('mb_convert_encoding')) return mb_convert_encoding($string, $toCharset, $fromCharset); + if(function_exists('iconv')) return iconv($fromCharset, $toCharset, $string); + if(function_exists('recode_string')) return recode_string($fromCharset .'..'. $toCharset, $string); + + throw new PListException('neither iconv nor mbstring supported. how are we supposed to work on strings here?'); + } + + /** + * Count characters considering character set + * Trying to use MBString, Iconv - in that particular order. + * @param string $string the string to convert + * @param string $charset the charset the given string is currently encoded in + * @return integer The number of characters in that string + * @throws PListException on neither MBString, Iconv being available + */ + public static function charsetStrlen($string,$charset="UTF-8") { + if(function_exists('mb_strlen')) return mb_strlen($string, $charset); + if(function_exists('iconv_strlen')) return iconv($string,$charset); + + throw new PListException('neither iconv nor mbstring supported. how are we supposed to work on strings here?'); + } + + /** + * Read a unicode string value, coded as UTF-16BE + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The length (in bytes) of the string value + * @return CFString The string value, utf8 encoded + * @throws IOException if read error occurs + */ + protected function readBinaryUnicodeString($fname,$fd,$length) { + if(strlen($buff = fread($fd, 2*$length)) != 2*$length) throw IOException::readError($fname); + + if(!isset($this->uniqueTable[$buff])) $this->uniqueTable[$buf] = true; + return new CFString(self::convertCharset($buff,"UTF-8", "UTF-16BE")); + } + + /** + * Read an array value, including contained objects + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The number of contained objects + * @return CFArray The array value, including the objects + * @throws IOException if read error occurs + */ + protected function readBinaryArray($fname,$fd,$length) { + $ary = new CFArray(); + + // first: read object refs + if($length != 0) { + if(strlen($buff = fread($fd, $length * $this->objectRefSize)) != $length * $this->objectRefSize) throw IOException::readError($fname); + $objects = unpack($this->objectRefSize == 1 ? "C*" : "n*", $buff); + + // now: read objects + for($i=0;$i<$length;++$i) { + $object = $this->readBinaryObjectAt($fname,$fd,$objects[$i+1]+1,$this->objectRefSize); + $ary->add($object); + } + } + + return $ary; + } + + /** + * Read a dictionary value, including contained objects + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $length The number of contained objects + * @return CFDictionary The dictionary value, including the objects + * @throws IOException if read error occurs + */ + protected function readBinaryDict($fname,$fd,$length) { + $dict = new CFDictionary(); + + // first: read keys + if($length != 0) { + if(strlen($buff = fread($fd, $length * $this->objectRefSize)) != $length * $this->objectRefSize) throw IOException::readError($fname); + $keys = unpack(($this->objectRefSize == 1 ? "C*" : "n*"), $buff); + + // second: read object refs + if(strlen($buff = fread($fd, $length * $this->objectRefSize)) != $length * $this->objectRefSize) throw IOException::readError($fname); + $objects = unpack(($this->objectRefSize == 1 ? "C*" : "n*"), $buff); + + // read real keys and objects + for($i=0;$i<$length;++$i) { + $key = $this->readBinaryObjectAt($fname,$fd,$keys[$i+1]+1); + $object = $this->readBinaryObjectAt($fname,$fd,$objects[$i+1]+1); + $dict->add($key->getValue(),$object); + } + } + + return $dict; + } + + /** + * Read an object type byte, decode it and delegate to the correct reader function + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @return mixed The value of the delegate reader, so any of the CFType subclasses + * @throws IOException if read error occurs + */ + function readBinaryObject($fname,$fd) { + // first: read the marker byte + if(strlen($buff = fread($fd,1)) != 1) throw IOException::readError($fname); + + $object_length = unpack("C*", $buff); + $object_length = $object_length[1] & 0xF; + $buff = unpack("H*", $buff); + $buff = $buff[1]; + + $object_type = substr($buff, 0, 1); + if($object_type != "0" && $object_length == 15) { + $object_length = $this->readBinaryObject($fname,$fd,$this->objectRefSize); + $object_length = $object_length->getValue(); + } + + $retval = null; + switch($object_type) { + case '0': // null, false, true, fillbyte + $retval = $this->readBinaryNullType($object_length); + break; + case '1': // integer + $retval = $this->readBinaryInt($fname,$fd,$object_length); + break; + case '2': // real + $retval = $this->readBinaryReal($fname,$fd,$object_length); + break; + case '3': // date + $retval = $this->readBinaryDate($fname,$fd,$object_length); + break; + case '4': // data + $retval = $this->readBinaryData($fname,$fd,$object_length); + break; + case '5': // byte string, usually utf8 encoded + $retval = $this->readBinaryString($fname,$fd,$object_length); + break; + case '6': // unicode string (utf16be) + $retval = $this->readBinaryUnicodeString($fname,$fd,$object_length); + break; + case 'a': // array + $retval = $this->readBinaryArray($fname,$fd,$object_length); + break; + case 'd': // dictionary + $retval = $this->readBinaryDict($fname,$fd,$object_length); + break; + } + + return $retval; + } + + /** + * Read an object type byte at position $pos, decode it and delegate to the correct reader function + * @param string $fname The filename of the file we're reading from + * @param ressource $fd The file descriptor we're reading from + * @param integer $pos The table position in the offsets table + * @return mixed The value of the delegate reader, so any of the CFType subclasses + */ + function readBinaryObjectAt($fname,$fd,$pos) { + $position = $this->offsets[$pos]; + fseek($fd,$position,SEEK_SET); + return $this->readBinaryObject($fname,$fd); + } + + /** + * Read a binary plist file + * @param string $file The file to read + * @return void + * @throws IOException if read error occurs + */ + function readBinary($file) { + $this->uniqueTable = Array(); + $this->countObjects = 0; + $this->stringSize = 0; + $this->intSize = 0; + $this->miscSize = 0; + $this->objectRefs = 0; + + $this->writtenObjectCount = 0; + $this->objectTable = Array(); + $this->objectRefSize = 0; + + $this->offsets = Array(); + + $fd = fopen($file,"rb"); + + // first, we read the trailer: 32 byte from the end + fseek($fd,-32,SEEK_END); + $buff = fread($fd,32); + + $infos = unpack("x6/Coffset_size/Cobject_ref_size/x4/Nnumber_of_objects/x4/Ntop_object/x4/Ntable_offset",$buff); + + // after that, get the offset table + fseek($fd,$infos['table_offset'], SEEK_SET); + $coded_offset_table = fread($fd,$infos['number_of_objects'] * $infos['offset_size']); + if(strlen($coded_offset_table) != $infos['number_of_objects'] * $infos['offset_size']) throw IOException::readError($file); + $this->countObjects = $infos['number_of_objects']; + + // decode offset table + $formats = Array("","C*","n*","(H6)*","N*"); + $this->offsets = unpack($formats[$infos['offset_size']],$coded_offset_table); + if($infos['offset_size'] == 3) { + foreach($this->offsets as $k => $v) $this->offsets[$k] = hexdec($v); + } + + $this->uniqueTable = Array(); + $this->objectRefSize = $infos['object_ref_size']; + + $top = $this->readBinaryObjectAt($file,$fd,$infos['top_object']+1); + $this->add($top); + + fclose($fd); + } + + /** + * calculate the bytes needed for a size integer value + * @param integer $int The integer value to calculate + * @return integer The number of bytes needed + */ + public static function bytesSizeInt($int) { + $nbytes = 0; + + if($int > 0xE) $nbytes += 2; // 2 size-bytes + if($int > 0xFF) $nbytes += 1; // 3 size-bytes + if($int > 0xFFFF) $nbytes += 2; // 5 size-bytes + + return $nbytes; + } + + /** + * Calculate the byte needed for a „normal” integer value + * @param integer $int The integer value + * @return integer The number of bytes needed + 1 (because of the „marker byte”) + */ + public static function bytesInt($int) { + $nbytes = 1; + + if($int > 0xFF) $nbytes += 1; // 2 byte integer + if($int > 0xFFFF) $nbytes += 2; // 4 byte integer + if($int > 0xFFFFFFFF) $nbytes += 4; // 8 byte integer + if($int < 0) $nbytes += 7; // 8 byte integer (since it is signed) + + return $nbytes + 1; // one „marker” byte + } + + /** + * „pack” a value (i.e. write the binary representation as big endian to a string) with the specified size + * @param integer $nbytes The number of bytes to pack + * @param integer $int the integer value to pack + * @return string The packed value as string + */ + public static function packItWithSize($nbytes,$int) { + $formats = Array("C", "n", "N", "N"); + $format = $formats[$nbytes-1]; + $ret = ''; + + if($nbytes == 3) return substr(pack($format, $int), -3); + return pack($format, $int); + } + + /** + * Calculate the bytes needed to save the number of objects + * @param integer $count_objects The number of objects + * @return integer The number of bytes + */ + public static function bytesNeeded($count_objects) { + $nbytes = 0; + + while($count_objects >= 1) { + $nbytes++; + $count_objects /= 256; + } + + return $nbytes; + } + + /** + * Code an integer to byte representation + * @param integer $int The integer value + * @return string The packed byte value + */ + public static function intBytes($int) { + $intbytes = ""; + + if($int > 0xFFFF) $intbytes = "\x12".pack("N", $int); // 4 byte integer + elseif($int > 0xFF) $intbytes = "\x11".pack("n", $int); // 2 byte integer + else $intbytes = "\x10".pack("C", $int); // 8 byte integer + + return $intbytes; + } + + /** + * Code an type byte, consisting of the type marker and the length of the type + * @param string $type The type byte value (i.e. "d" for dictionaries) + * @param integer $type_len The length of the type + * @return string The packed type byte value + */ + public static function typeBytes($type,$type_len) { + $optional_int = ""; + + if($type_len < 15) $type .= sprintf("%x", $type_len); + else { + $type .= "f"; + $optional_int = self::intBytes($type_len); + } + + return pack("H*", $type).$optional_int; + } + + /** + * Count number of objects and create a unique table for strings + * @param $value The value to count and unique + * @return void + */ + protected function uniqueAndCountValues($value) { + // no uniquing for other types than CFString and CFData + if($value instanceof CFNumber) { + $val = $value->getValue(); + if(intval($val) == $val && !is_float($val) && strpos($val,'.') === false) $this->intSize += self::bytesInt($val); + else $this->miscSize += 9; // 9 bytes (8 + marker byte) for real + $this->countObjects++; + return; + } + elseif($value instanceof CFDate) { + $this->miscSize += 9; // since date in plist is real, we need 9 byte (8 + marker byte) + $this->countObjects++; + return; + } + elseif($value instanceof CFBoolean) { + $this->countObjects++; + $this->miscSize += 1; + return; + } + elseif($value instanceof CFArray) { + $cnt = 0; + foreach($value as $v) { + ++$cnt; + $this->uniqueAndCountValues($v); + $this->objectRefs++; // each array member is a ref + } + + $this->countObjects++; + $this->intSize += self::bytesSizeInt($cnt); + $this->miscSize++; // marker byte for array + return; + } + elseif($value instanceof CFDictionary) { + $cnt = 0; + foreach($value as $k => $v) { + ++$cnt; + if(!isset($this->uniqueTable[$k])) { + $this->uniqueTable[$k] = 0; + $this->stringSize += strlen($k) + 1; + $this->intSize += self::bytesSizeInt(strlen($k)); + } + + $this->objectRefs += 2; // both, key and value, are refs + $this->uniqueTable[$k]++; + $this->uniqueAndCountValues($v); + } + + $this->countObjects++; + $this->miscSize++; // marker byte for dict + $this->intSize += self::bytesSizeInt($cnt); + return; + } + elseif($value instanceOf CFData) { + $val = $value->getValue(); + $this->intSize += self::bytesSizeInt(strlen($val)); + $this->miscSize += strlen($val) + 1; + $this->countObjects++; + return; + } + else $val = $value->getValue(); + + if(!isset($this->uniqueTable[$val])) { + $this->uniqueTable[$val] = 0; + $this->stringSize += strlen($val) + 1; + $this->intSize += self::bytesSizeInt(strlen($val)); + } + $this->uniqueTable[$val]++; + } + + /** + * Convert CFPropertyList to binary format; since we have to count our objects we simply unique CFDictionary and CFArray + * @return string The binary plist content + */ + public function toBinary() { + $this->uniqueTable = Array(); + $this->countObjects = 0; + $this->stringSize = 0; + $this->intSize = 0; + $this->miscSize = 0; + $this->objectRefs = 0; + + $this->writtenObjectCount = 0; + $this->objectTable = Array(); + $this->objectRefSize = 0; + + $this->offsets = Array(); + + $binary_str = "bplist00"; + $value = $this->getValue(); + $this->uniqueAndCountValues($value); + + $this->countObjects += count($this->uniqueTable); + $this->objectRefSize = self::bytesNeeded($this->countObjects); + $file_size = $this->stringSize + $this->intSize + $this->miscSize + $this->objectRefs * $this->objectRefSize + 40; + $offset_size = self::bytesNeeded($file_size); + $table_offset = $file_size - 32; + + $this->objectTable = Array(); + $this->writtenObjectCount = 0; + $this->uniqueTable = Array(); // we needed it to calculate several values + $this->getValue()->toBinary($this); + + $object_offset = 8; + $offsets = Array(); + + for($i=0;$iobjectTable);++$i) { + $binary_str .= $this->objectTable[$i]; + $offsets[$i] = $object_offset; + $object_offset += strlen($this->objectTable[$i]); + } + + for($i=0;$iobjectRefSize); + $binary_str .= pack("x4N", $this->countObjects); + $binary_str .= pack("x4N", 0); + $binary_str .= pack("x4N", $table_offset); + + return $binary_str; + } + + /** + * Uniques and transforms a string value to binary format and adds it to the object table + * @param string $val The string value + * @return integer The position in the object table + */ + public function stringToBinary($val) { + $saved_object_count = -1; + + if(!isset($this->uniqueTable[$val])) { + $saved_object_count = $this->writtenObjectCount++; + $this->uniqueTable[$val] = $saved_object_count; + $utf16 = false; + + for($i=0;$i 128) { + $utf16 = true; + break; + } + } + + if($utf16) { + $bdata = self::typeBytes("6", mb_strlen($val,'UTF-8')); // 6 is 0110, unicode string (utf16be) + $val = self::convertCharset($val, 'UTF-8', 'UTF-16BE'); + $this->objectTable[$saved_object_count] = $bdata.$val; + } + else { + $bdata = self::typeBytes("5", strlen($val)); // 5 is 0101 which is an ASCII string (seems to be ASCII encoded) + $this->objectTable[$saved_object_count] = $bdata.$val; + } + } + else $saved_object_count = $this->uniqueTable[$val]; + + return $saved_object_count; + } + + /** + * Codes an integer to binary format + * @param integer $value The integer value + * @return string the coded integer + */ + protected function intToBinary($value) { + $nbytes = 0; + if($value > 0xFF) $nbytes = 1; // 1 byte integer + if($value > 0xFFFF) $nbytes += 1; // 4 byte integer + if($value > 0xFFFFFFFF) $nbytes += 1; // 8 byte integer + if($value < 0) $nbytes = 3; // 8 byte integer, since signed + + $bdata = self::typeBytes("1", $nbytes); // 1 is 0001, type indicator for integer + $buff = ""; + + if($nbytes < 3) { + if($nbytes == 0) $fmt = "C"; + elseif($nbytes == 1) $fmt = "n"; + else $fmt = "N"; + + $buff = pack($fmt, $value); + } + else { + if(PHP_INT_SIZE > 4) { + // 64 bit signed integer; we need the higher and the lower 32 bit of the value + $high_word = $value >> 32; + $low_word = $value & 0xFFFFFFFF; + } + else { + // since PHP can only handle 32bit signed, we can only get 32bit signed values at this point - values above 0x7FFFFFFF are + // floats. So we ignore the existance of 64bit on non-64bit-machines + if($value < 0) $high_word = 0xFFFFFFFF; + else $high_word = 0; + $low_word = $value; + } + $buff = pack("N", $high_word).pack("N", $low_word); + } + + return $bdata.$buff; + } + + /** + * Codes a real value to binary format + * @param float $val The real value + * @return string The coded real + */ + protected function realToBinary($val) { + $bdata = self::typeBytes("2", 3); // 2 is 0010, type indicator for reals + return $bdata.strrev(pack("d", (float)$val)); + } + + /** + * Converts a numeric value to binary and adds it to the object table + * @param numeric $value The numeric value + * @return integer The position in the object table + */ + public function numToBinary($value) { + $saved_object_count = $this->writtenObjectCount++; + + $val = ""; + if(intval($value) == $value && !is_float($value) && strpos($value,'.') === false) $val = $this->intToBinary($value); + else $val = $this->realToBinary($value); + + $this->objectTable[$saved_object_count] = $val; + return $saved_object_count; + } + + /** + * Convert date value (apple format) to binary and adds it to the object table + * @param integer $value The date value + * @return integer The position of the coded value in the object table + */ + public function dateToBinary($val) { + $saved_object_count = $this->writtenObjectCount++; + + $hour = gmdate("H",$val); + $min = gmdate("i",$val); + $sec = gmdate("s",$val); + $mday = gmdate("j",$val); + $mon = gmdate("n",$val); + $year = gmdate("Y",$val); + + $val = gmmktime($hour,$min,$sec,$mon,$mday,$year) - CFDate::DATE_DIFF_APPLE_UNIX; // CFDate is a real, number of seconds since 01/01/2001 00:00:00 GMT + + $bdata = self::typeBytes("3", 3); // 3 is 0011, type indicator for date + $this->objectTable[$saved_object_count] = $bdata.strrev(pack("d", $val)); + + return $saved_object_count; + } + + /** + * Convert a bool value to binary and add it to the object table + * @param bool $val The boolean value + * @return integer The position in the object table + */ + public function boolToBinary($val) { + $saved_object_count = $this->writtenObjectCount++; + $this->objectTable[$saved_object_count] = $val ? "\x9" : "\x8"; // 0x9 is 1001, type indicator for true; 0x8 is 1000, type indicator for false + return $saved_object_count; + } + + /** + * Convert data value to binary format and add it to the object table + * @param string $val The data value + * @return integer The position in the object table + */ + public function dataToBinary($val) { + $saved_object_count = $this->writtenObjectCount++; + + $bdata = self::typeBytes("4", strlen($val)); // a is 1000, type indicator for data + $this->objectTable[$saved_object_count] = $bdata.$val; + + return $saved_object_count; + } + + /** + * Convert array to binary format and add it to the object table + * @param CFArray $val The array to convert + * @return integer The position in the object table + */ + public function arrayToBinary($val) { + $saved_object_count = $this->writtenObjectCount++; + + $bdata = self::typeBytes("a", count($val->getValue())); // a is 1010, type indicator for arrays + + foreach($val as $v) { + $bval = $v->toBinary($this); + $bdata .= self::packItWithSize($this->objectRefSize, $bval); + } + + $this->objectTable[$saved_object_count] = $bdata; + return $saved_object_count; + } + + /** + * Convert dictionary to binary format and add it to the object table + * @param CFDictionary $val The dict to convert + * @return integer The position in the object table + */ + public function dictToBinary($val) { + $saved_object_count = $this->writtenObjectCount++; + $bdata = self::typeBytes("d", count($val->getValue())); // d=1101, type indicator for dictionary + + foreach($val as $k => $v) { + $str = new CFString($k); + $key = $str->toBinary($this); + $bdata .= self::packItWithSize($this->objectRefSize, $key); + } + + foreach($val as $k => $v) { + $bval = $v->toBinary($this); + $bdata .= self::packItWithSize($this->objectRefSize, $bval); + } + + $this->objectTable[$saved_object_count] = $bdata; + return $saved_object_count; + } + +} + + +?> diff --git a/Tools/projectGenerator/classes/plist/CFPropertyList.php b/Tools/projectGenerator/classes/plist/CFPropertyList.php new file mode 100644 index 000000000..6543ba5c3 --- /dev/null +++ b/Tools/projectGenerator/classes/plist/CFPropertyList.php @@ -0,0 +1,524 @@ + + * @author Christian Kruse + * @package plist + * @version $Id$ + * @example example-read-01.php Read an XML PropertyList + * @example example-read-02.php Read a Binary PropertyList + * @example example-read-03.php Read a PropertyList without knowing the type + * @example example-create-01.php Using the CFPropertyList API + * @example example-create-02.php Using CFPropertyList::guess() + * @example example-create-03.php Using CFPropertyList::guess() with {@link CFDate} and {@link CFData} + */ + +/** + * Require IOException, PListException, CFType and CFBinaryPropertyList + */ +$plistDirectory = dirname(__FILE__); +require_once($plistDirectory.'/IOException.php'); +require_once($plistDirectory.'/PListException.php'); +require_once($plistDirectory.'/CFType.php'); +require_once($plistDirectory.'/CFBinaryPropertyList.php'); + +/** + * Property List + * Interface for handling reading, editing and saving Property Lists as defined by Apple. + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @example example-read-01.php Read an XML PropertyList + * @example example-read-02.php Read a Binary PropertyList + * @example example-read-03.php Read a PropertyList without knowing the type + * @example example-create-01.php Using the CFPropertyList API + * @example example-create-02.php Using CFPropertyList::guess() + * @example example-create-03.php Using CFPropertyList::guess() with {@link CFDate} and {@link CFData} + */ +class CFPropertyList extends CFBinaryPropertyList implements Iterator { + /** + * Format constant for binary format + * @var integer + */ + const FORMAT_BINARY = 1; + + /** + * Format constant for xml format + * @var integer + */ + const FORMAT_XML = 2; + + /** + * Format constant for automatic format recognizing + * @var integer + */ + const FORMAT_AUTO = 0; + + /** + * Path of PropertyList + * @var string + */ + protected $file = null; + + /** + * Path of PropertyList + * @var integer + */ + protected $format = null; + + /** + * CFType nodes + * @var array + */ + protected $value = array(); + + /** + * Position of iterator {@link http://php.net/manual/en/class.iterator.php} + * @var integer + */ + protected $iteratorPosition = 0; + + /** + * List of Keys for numerical iterator access {@link http://php.net/manual/en/class.iterator.php} + * @var array + */ + protected $iteratorKeys = null; + + /** + * List of NodeNames to ClassNames for resolving plist-files + * @var array + */ + protected static $types = array( + 'string' => 'CFString', + 'real' => 'CFNumber', + 'integer' => 'CFNumber', + 'date' => 'CFDate', + 'true' => 'CFBoolean', + 'false' => 'CFBoolean', + 'data' => 'CFData', + 'array' => 'CFArray', + 'dict' => 'CFDictionary' + ); + + + /** + * Create new CFPropertyList. + * If a path to a PropertyList is specified, it is loaded automatically. + * @param string $file Path of PropertyList + * @param integer $format he format of the property list, see {@link FORMAT_XML}, {@link FORMAT_BINARY} and {@link FORMAT_AUTO}, defaults to {@link FORMAT_AUTO} + * @throws IOException if file could not be read by {@link load()} + * @uses $file for storing the current file, if specified + * @uses load() for loading the plist-file + */ + public function __construct($file=null,$format=self::FORMAT_AUTO) { + $this->file = $file; + $this->format = $format; + if($this->file) $this->load(); + } + + /** + * Load an XML PropertyList. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @return void + * @throws IOException if file could not be read + * @throws DOMException if XML-file could not be read properly + * @uses load() to actually load the file + */ + public function loadXML($file=null) { + $this->load($file,CFPropertyList::FORMAT_XML); + } + + /** + * Load an binary PropertyList. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @return void + * @throws IOException if file could not be read + * @throws PListException if binary plist-file could not be read properly + * @uses load() to actually load the file + */ + public function loadBinary($file=null) { + $this->load($file,CFPropertyList::FORMAT_BINARY); + } + + /** + * Load a plist file. + * Load and import a plist file. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @param integer $format The format of the property list, see {@link FORMAT_XML}, {@link FORMAT_BINARY} and {@link FORMAT_AUTO}, defaults to {@link $format} + * @return void + * @throws PListException if file format version is not 00 + * @throws IOException if file could not be read + * @throws DOMException if plist file could not be parsed properly + * @uses $file if argument $file was not specified + * @uses $value reset to empty array + * @uses import() for importing the values + */ + public function load($file=null,$format=null) { + $file = $file ? $file : $this->file; + $format = $format !== null ? $format : $this->format; + $this->value = array(); + + if(!is_readable($file)) throw IOException::notReadable($file); + + switch($format) { + case CFPropertyList::FORMAT_BINARY: + $this->readBinary($file); + break; + case CFPropertyList::FORMAT_AUTO: // what we now do is ugly, but neccessary to recognize the file format + $fd = fopen($file,"rb"); + if(($magic_number = fread($fd,8)) === false) throw IOException::notReadable($file); + fclose($fd); + + $filetype = substr($magic_number,0,6); + $version = substr($magic_number,-2); + + if($filetype == "bplist") { + if($version != "00") throw new PListException("Wrong file format version! Expected 00, got $version!"); + $this->readBinary($file); + break; + } + // else: xml format, break not neccessary + case CFPropertyList::FORMAT_XML: + $doc = new DOMDocument(); + if(!$doc->load($file)) throw new DOMException(); + $this->import($doc->documentElement, $this); + break; + } + + } + + /** + * Convert a DOMNode into a CFType. + * @param DOMNode $node Node to import children of + * @param CFDictionary|CFArray|CFPropertyList $parent + * @return void + */ + protected function import(DOMNode $node, $parent) { + // abort if there are no children + if(!$node->childNodes->length) return; + + foreach($node->childNodes as $n) { + // skip if we can't handle the element + if(!isset(self::$types[$n->nodeName])) continue; + + $class = self::$types[$n->nodeName]; + $key = null; + + // find previous if possible + $ps = $n->previousSibling; + while($ps && $ps->nodeName == '#text' && $ps->previousSibling) $ps = $ps->previousSibling; + + // read if possible + if($ps && $ps->nodeName == 'key') $key = $ps->firstChild->nodeValue; + + switch($n->nodeName) { + case 'date': + $value = new $class(CFDate::dateValue($n->nodeValue)); + break; + case 'data': + $value = new $class($n->nodeValue,true); + break; + case 'string': + $value = new $class($n->nodeValue); + break; + + case 'real': + case 'integer': + $value = new $class($n->nodeName == 'real' ? floatval($n->nodeValue) : intval($n->nodeValue)); + break; + + case 'true': + case 'false': + $value = new $class($n->nodeName == 'true'); + break; + + case 'array': + case 'dict': + $value = new $class(); + $this->import($n, $value); + break; + } + + // Dictionaries need a key + if($parent instanceof CFDictionary) $parent->add($key, $value); + // others don't + else $parent->add($value); + } + } + + /** + * Convert CFPropertyList to XML and save to file. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @return void + * @throws IOException if file could not be read + * @uses $file if $file was not specified + */ + public function saveXML($file) { + $this->save($file,CFPropertyList::FORMAT_XML); + } + + /** + * Convert CFPropertyList to binary format (bplist00) and save to file. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @return void + * @throws IOException if file could not be read + * @uses $file if $file was not specified + */ + public function saveBinary($file) { + $this->save($file,CFPropertyList::FORMAT_BINARY); + } + + /** + * Convert CFPropertyList to XML or binary and save to file. + * @param string $file Path of PropertyList, defaults to {@link $file} + * @param string $format Format of PropertyList, defaults to {@link $format} + * @return void + * @throws IOException if file could not be read + * @throws PListException if evaluated $format is neither {@link FORMAT_XML} nor {@link FORMAL_BINARY} + * @uses $file if $file was not specified + * @uses $format if $format was not specified + */ + public function save($file=null,$format=null) { + $file = $file ? $file : $this->file; + $format = $format ? $format : $this->format; + + if( !in_array( $format, array( self::FORMAT_BINARY, self::FORMAT_XML ) ) ) + throw new PListException( "format {$format} is not supported, use CFPropertyList::FORMAT_BINARY or CFPropertyList::FORMAT_XML" ); + + if(!file_exists($file)) { + // dirname("file.xml") == "" and is treated as the current working directory + if(!is_writable(dirname($file))) throw IOException::notWritable($file); + } + else if(!is_writable($file)) throw IOException::notWritable($file); + + $content = $format == self::FORMAT_BINARY ? $this->toBinary() : $this->toXML(); + + $fh = fopen($file, 'wb'); + fwrite($fh,$content); + fclose($fh); + } + + /** + * Convert CFPropertyList to XML + * @param bool $formatted Print plist formatted (i.e. with newlines and whitespace indention) if true; defaults to false + * @return string The XML content + */ + public function toXML($formatted=false) { + $domimpl = new DOMImplementation(); + // + $dtd = $domimpl->createDocumentType('plist', '-//Apple Computer//DTD PLIST 1.0//EN', 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'); + $doc = $domimpl->createDocument(null, "plist", $dtd); + $doc->encoding = "UTF-8"; + + // format output + if($formatted) { + $doc->formatOutput = true; + $doc->preserveWhiteSpace = true; + } + + // get documentElement and set attribs + $plist = $doc->documentElement; + $plist->setAttribute('version', '1.0'); + + // add PropertyList's children + $plist->appendChild($this->getValue()->toXML($doc)); + + return $doc->saveXML(); + } + + + /************************************************************************************************ + * M A N I P U L A T I O N + ************************************************************************************************/ + + /** + * Add CFType to collection. + * @param CFType $value CFType to add to collection + * @return void + * @uses $value for adding $value + */ + public function add($value) { + $this->value[] = $value; + } + + /** + * Get CFType from collection. + * @param integer $key Key of CFType to retrieve from collection + * @return CFType CFType found at $key, null else + * @uses $value for retrieving CFType of $key + */ + public function get($key) { + if(isset($this->value[$key])) return $this->value[$key]; + return null; + } + + /** + * Remove CFType from collection. + * @param integer $key Key of CFType to removes from collection + * @return CFType removed CFType, null else + * @uses $value for removing CFType of $key + */ + public function del($key) { + if(isset($this->value[$key])) { + $t = $this->value[$key]; + unset($this->value[$key]); + return $t; + } + + return null; + } + + /** + * Get first (and only) child, or complete collection. + * @return CFType|array CFType or list of CFTypes known to the PropertyList + * @uses $value for retrieving CFTypes + */ + public function getValue() { + if(count($this->value) === 1) return $this->value[0]; + return $this->value; + } + + /** + * Create CFType-structure from guessing the data-types. + * {@link CFArray}, {@link CFDictionary}, {@link CFBoolean}, {@link CFNumber} and {@link CFString} can be created, {@link CFDate} and {@link CFData} cannot. + *
Note:Distinguishing between {@link CFArray} and {@link CFDictionary} is done by examining the keys. + * Keys must be strictly incrementing integers to evaluate to a {@link CFArray}. + * Since PHP does not offer a function to test for associative arrays, + * this test causes the input array to be walked twice and thus work rather slow on large collections. + * If you work with large arrays and can live with all arrays evaluating to {@link CFDictionary}, + * feel free to set the appropriate flag. + *
Note: If $value is an instance of CFType it is simply returned. + *
Note: If $value is neither a CFType, array, numeric, boolean nor string, it is omitted. + * @param mixed $value Value to convert to CFType + * @param boolean $autoDictionary if true {@link CFArray}-detection is bypassed and arrays will be returned as {@link CFDictionary}. + * @return CFType CFType based on guessed type + */ + public static function guess($value, $autoDictionary=false) { + switch(true) { + case $value instanceof CFType: + return $value; + break; + case is_array($value): + // test if $value is simple or associative array + if(!$autoDictionary) { + $numericKeys = true; + $previousKey = null; + foreach($value as $key => $v) { + if(!is_numeric($key) || ($previousKey !== null && $previousKey != $key-1)) { + $numericKeys = false; + break; + } + + $previousKey = $key; + } + + if($numericKeys) { + $t = new CFArray(); + foreach($value as $v) $t->add(self::guess($v, $autoDictionary)); + return $t; + } + } + + $t = new CFDictionary(); + foreach($value as $k => $v) $t->add($k, self::guess($v, $autoDictionary)); + + return $t; + break; + + case is_numeric($value): + return new CFNumber($value); + break; + + case is_bool($value): + return new CFBoolean($value); + break; + + case is_string($value): + return new CFString($value); + break; + } + } + + + /************************************************************************************************ + * S E R I A L I Z I N G + ************************************************************************************************/ + + /** + * Get PropertyList as array. + * @return mixed primitive value of first (and only) CFType, or array of primitive values of collection + * @uses $value for retrieving CFTypes + */ + public function toArray() { + $a = array(); + foreach($this->value as $value) $a[] = $value->toArray(); + if(count($a) === 1) return $a[0]; + + return $a; + } + + + /************************************************************************************************ + * I T E R A T O R I N T E R F A C E + ************************************************************************************************/ + + /** + * Rewind {@link $iteratorPosition} to first position (being 0) + * @link http://php.net/manual/en/iterator.rewind.php + * @return void + * @uses $iteratorPosition set to 0 + * @uses $iteratorKeys store keys of {@link $value} + */ + public function rewind() { + $this->iteratorPosition = 0; + $this->iteratorKeys = array_keys($this->value); + } + + /** + * Get Iterator's current {@link CFType} identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.current.php + * @return CFType current Item + * @uses $iteratorPosition identify current key + * @uses $iteratorKeys identify current value + */ + public function current() { + return $this->value[$this->iteratorKeys[$this->iteratorPosition]]; + } + + /** + * Get Iterator's current key identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.key.php + * @return string key of the current Item + * @uses $iteratorPosition identify current key + * @uses $iteratorKeys identify current value + */ + public function key() { + return $this->iteratorKeys[$this->iteratorPosition]; + } + + /** + * Increment {@link $iteratorPosition} to address next {@see CFType} + * @link http://php.net/manual/en/iterator.next.php + * @return void + * @uses $iteratorPosition increment by 1 + */ + public function next() { + $this->iteratorPosition++; + } + + /** + * Test if {@link $iteratorPosition} addresses a valid element of {@link $value} + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean true if current position is valid, false else + * @uses $iteratorPosition test if within {@link $iteratorKeys} + * @uses $iteratorPosition test if within {@link $value} + */ + public function valid() { + return isset($this->iteratorKeys[$this->iteratorPosition]) && isset($this->value[$this->iteratorKeys[$this->iteratorPosition]]); + } + +} + + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/classes/plist/CFType.php b/Tools/projectGenerator/classes/plist/CFType.php new file mode 100644 index 000000000..75d5131ff --- /dev/null +++ b/Tools/projectGenerator/classes/plist/CFType.php @@ -0,0 +1,661 @@ + + * @author Christian Kruse + * @package plist + * @subpackage plist.types + * @version $Id$ + */ + +/** + * Base-Class of all CFTypes used by CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + * @version $Id$ + * @example example-create-01.php Using the CFPropertyList API + * @example example-create-02.php Using CFPropertyList::guess() + * @example example-create-03.php Using CFPropertyList::guess() with {@link CFDate} and {@link CFData} + */ +abstract class CFType { + /** + * CFType nodes + * @var array + */ + protected $value = null; + + /** + * Create new CFType. + * @param mixed $value Value of CFType + */ + public function __construct($value=null) { + $this->setValue($value); + } + + /************************************************************************************************ + * M A G I C P R O P E R T I E S + ************************************************************************************************/ + + /** + * Get the CFType's value + * @return mixed CFType's value + */ + public function getValue() { + return $this->value; + } + + /** + * Set the CFType's value + * @return void + */ + public function setValue($value) { + $this->value = $value; + } + + /************************************************************************************************ + * S E R I A L I Z I N G + ************************************************************************************************/ + + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @param string $nodeName Name of element to create + * @return DOMNode Node created based on CType + * @uses $value as nodeValue + */ + public function toXML(DOMDocument $doc, $nodeName) { + $text = $doc->createTextNode($this->value); + $node = $doc->createElement($nodeName); + $node->appendChild($text); + return $node; + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public abstract function toBinary(CFBinaryPropertyList &$bplist); + + /** + * Get CFType's value. + * @return mixed primitive value + * @uses $value for retrieving primitive of CFType + */ + public function toArray() { + return $this->getValue(); + } + +} + +/** + * String Type of CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFString extends CFType { + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <string>-Element + */ + public function toXML(DOMDocument $doc) { + return parent::toXML($doc, 'string'); + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->stringToBinary($this->value); + } +} + +/** + * Number Type of CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFNumber extends CFType { + /** + * Get XML-Node. + * Returns <real> if $value is a float, <integer> if $value is an integer. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <real> or <integer>-Element + */ + public function toXML(DOMDocument $doc) { + $ret = 'real'; + if(intval($this->value) == $this->value && !is_float($this->value) && strpos($this->value,'.') === false) { + $this->value = intval($this->value); + $ret = 'integer'; + } + return parent::toXML($doc, $ret); + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->numToBinary($this->value); + } +} + +/** + * Date Type of CFPropertyList + * Note: CFDate uses Unix timestamp (epoch) to store dates internally + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFDate extends CFType { + const TIMESTAMP_APPLE = 0; + const TIMESTAMP_UNIX = 1; + const DATE_DIFF_APPLE_UNIX = 978307200; + + /** + * Create new Date CFType. + * @param integer $value timestamp to set + * @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_APPLE} + * @uses setValue() to convert the timestamp + */ + function __construct($value,$format=CFDate::TIMESTAMP_UNIX) { + $this->setValue($value,$format); + } + + /** + * Set the Date CFType's value. + * @param integer $value timestamp to set + * @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX} + * @return void + * @uses TIMESTAMP_APPLE to determine timestamp type + * @uses TIMESTAMP_UNIX to determine timestamp type + * @uses DATE_DIFF_APPLE_UNIX to convert Apple-timestamp to Unix-timestamp + */ + function setValue($value,$format=CFDate::TIMESTAMP_UNIX) { + if($format == CFDate::TIMESTAMP_UNIX) $this->value = $value; + else $this->value = $value + CFDate::DATE_DIFF_APPLE_UNIX; + } + + /** + * Get the Date CFType's value. + * @param integer $format format the timestamp is specified in, use {@link TIMESTAMP_APPLE} or {@link TIMESTAMP_UNIX}, defaults to {@link TIMESTAMP_UNIX} + * @return integer Unix timestamp + * @uses TIMESTAMP_APPLE to determine timestamp type + * @uses TIMESTAMP_UNIX to determine timestamp type + * @uses DATE_DIFF_APPLE_UNIX to convert Unix-timestamp to Apple-timestamp + */ + function getValue($format=CFDate::TIMESTAMP_UNIX) { + if($format == CFDate::TIMESTAMP_UNIX) return $this->value; + else return $this->value - CFDate::DATE_DIFF_APPLE_UNIX; + } + + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <date>-Element + */ + public function toXML(DOMDocument $doc) { + $text = $doc->createTextNode(gmdate("Y-m-d\TH:i:s\Z",$this->getValue())); + $node = $doc->createElement("date"); + $node->appendChild($text); + return $node; + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->dateToBinary($this->value); + } + + /** + * Create a UNIX timestamp from a PList date string + * @param string $val The date string (e.g. "2009-05-13T20:23:43Z") + * @return integer The UNIX timestamp + * @throws PListException when encountering an unknown date string format + */ + public static function dateValue($val) { + //2009-05-13T20:23:43Z + if(!preg_match('/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/',$val,$matches)) throw new PListException("Unknown date format: $val"); + return gmmktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]); + } +} + +/** + * Boolean Type of CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFBoolean extends CFType { + /** + * Get XML-Node. + * Returns <true> if $value is a true, <false> if $value is false. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <true> or <false>-Element + */ + public function toXML(DOMDocument $doc) { + return $doc->createElement($this->value ? 'true' : 'false'); + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->boolToBinary($this->value); + } + +} + +/** + * Data Type of CFPropertyList + * Note: Binary data is base64-encoded. + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFData extends CFType { + /** + * Create new Data CFType + * @param string $value data to be contained by new object + * @param boolean $already_coded if true $value will not be base64-encoded, defaults to false + */ + public function __construct($value=null,$already_coded=false) { + if($already_coded) $this->value = $value; + else $this->setValue($value); + } + + /** + * Set the CFType's value and base64-encode it. + * Note: looks like base64_encode has troubles with UTF-8 encoded strings + * @return void + */ + public function setValue($value) { + //if(function_exists('mb_check_encoding') && mb_check_encoding($value, 'UTF-8')) $value = utf8_decode($value); + $this->value = base64_encode($value); + } + + /** + * Get base64 encoded data + * @return string The base64 encoded data value + */ + public function getCodedValue() { + return $this->value; + } + + /** + * Get the base64-decoded CFType's value. + * @return mixed CFType's value + */ + public function getValue() { + return base64_decode($this->value); + } + + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <data>-Element + */ + public function toXML(DOMDocument $doc) { + return parent::toXML($doc, 'data'); + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->dataToBinary($this->getValue()); + } +} + +/** + * Array Type of CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFArray extends CFType implements Iterator { + /** + * Position of iterator {@link http://php.net/manual/en/class.iterator.php} + * @var integer + */ + protected $iteratorPosition = 0; + + + /** + * Create new CFType. + * @param array $value Value of CFType + */ + public function __construct($value=array()) { + $this->value = $value; + } + + /** + * Set the CFType's value + * Note: this dummy does nothing + * @return void + */ + public function setValue($value) { + } + + /** + * Add CFType to collection. + * @param CFType $value CFType to add to collection + * @return void + * @uses $value for adding $value + */ + public function add($value) { + $this->value[] = $value; + } + + /** + * Get CFType from collection. + * @param integer $key Key of CFType to retrieve from collection + * @return CFType CFType found at $key, null else + * @uses $value for retrieving CFType of $key + */ + public function get($key) { + if(isset($this->value[$key])) return $this->value[$key]; + return null; + } + + /** + * Remove CFType from collection. + * @param integer $key Key of CFType to removes from collection + * @return CFType removed CFType, null else + * @uses $value for removing CFType of $key + */ + public function del($key) { + if(isset($this->value[$key])) unset($this->value[$key]); + } + + + /************************************************************************************************ + * S E R I A L I Z I N G + ************************************************************************************************/ + + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <array>-Element + */ + public function toXML(DOMDocument $doc) { + $node = $doc->createElement('array'); + + foreach($this->value as $value) $node->appendChild($value->toXML($doc)); + return $node; + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->arrayToBinary($this); + } + + /** + * Get CFType's value. + * @return array primitive value + * @uses $value for retrieving primitive of CFType + */ + public function toArray() { + $a = array(); + foreach($this->value as $value) $a[] = $value->toArray(); + return $a; + } + + + /************************************************************************************************ + * I T E R A T O R I N T E R F A C E + ************************************************************************************************/ + + /** + * Rewind {@link $iteratorPosition} to first position (being 0) + * @link http://php.net/manual/en/iterator.rewind.php + * @return void + * @uses $iteratorPosition set to 0 + */ + public function rewind() { + $this->iteratorPosition = 0; + } + + /** + * Get Iterator's current {@link CFType} identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.current.php + * @return CFType current Item + * @uses $iteratorPosition identify current key + */ + public function current() { + return $this->value[$this->iteratorPosition]; + } + + /** + * Get Iterator's current key identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.key.php + * @return string key of the current Item + * @uses $iteratorPosition identify current key + */ + public function key() { + return $this->iteratorPosition; + } + + /** + * Increment {@link $iteratorPosition} to address next {@see CFType} + * @link http://php.net/manual/en/iterator.next.php + * @return void + * @uses $iteratorPosition increment by 1 + */ + public function next() { + $this->iteratorPosition++; + } + + /** + * Test if {@link $iteratorPosition} addresses a valid element of {@link $value} + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean true if current position is valid, false else + * @uses $iteratorPosition test if within {@link $iteratorKeys} + * @uses $iteratorPosition test if within {@link $value} + */ + public function valid() { + return isset($this->value[$this->iteratorPosition]); + } + +} + +/** + * Array Type of CFPropertyList + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + * @subpackage plist.types + */ +class CFDictionary extends CFType implements Iterator { + /** + * Position of iterator {@link http://php.net/manual/en/class.iterator.php} + * @var integer + */ + protected $iteratorPosition = 0; + + /** + * List of Keys for numerical iterator access {@link http://php.net/manual/en/class.iterator.php} + * @var array + */ + protected $iteratorKeys = null; + + + /** + * Create new CFType. + * @param array $value Value of CFType + */ + public function __construct($value=array()) { + $this->value = $value; + } + + /** + * Set the CFType's value + * Note: this dummy does nothing + * @return void + */ + public function setValue($value) { + } + + /** + * Add CFType to collection. + * @param string $key Key to add to collection + * @param CFType $value CFType to add to collection + * @return void + * @uses $value for adding $key $value pair + */ + public function add($key, $value) { + $this->value[$key] = $value; + } + + /** + * Get CFType from collection. + * @param string $key Key of CFType to retrieve from collection + * @return CFType CFType found at $key, null else + * @uses $value for retrieving CFType of $key + */ + public function get($key) { + if(isset($this->value[$key])) return $this->value[$key]; + return null; + } + + /** + * Remove CFType from collection. + * @param string $key Key of CFType to removes from collection + * @return CFType removed CFType, null else + * @uses $value for removing CFType of $key + */ + public function del($key) { + if(isset($this->value[$key])) unset($this->value[$key]); + } + + + /************************************************************************************************ + * S E R I A L I Z I N G + ************************************************************************************************/ + + /** + * Get XML-Node. + * @param DOMDocument $doc DOMDocument to create DOMNode in + * @return DOMNode <dict>-Element + */ + public function toXML(DOMDocument $doc) { + $node = $doc->createElement('dict'); + + foreach($this->value as $key => $value) { + $node->appendChild($doc->createElement('key', $key)); + $node->appendChild($value->toXML($doc)); + } + + return $node; + } + + /** + * convert value to binary representation + * @param CFBinaryPropertyList The binary property list object + * @return The offset in the object table + */ + public function toBinary(CFBinaryPropertyList &$bplist) { + return $bplist->dictToBinary($this); + } + + /** + * Get CFType's value. + * @return array primitive value + * @uses $value for retrieving primitive of CFType + */ + public function toArray() { + $a = array(); + + foreach($this->value as $key => $value) $a[$key] = $value->toArray(); + return $a; + } + + + /************************************************************************************************ + * I T E R A T O R I N T E R F A C E + ************************************************************************************************/ + + /** + * Rewind {@link $iteratorPosition} to first position (being 0) + * @link http://php.net/manual/en/iterator.rewind.php + * @return void + * @uses $iteratorPosition set to 0 + * @uses $iteratorKeys store keys of {@link $value} + */ + public function rewind() { + $this->iteratorPosition = 0; + $this->iteratorKeys = array_keys($this->value); + } + + /** + * Get Iterator's current {@link CFType} identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.current.php + * @return CFType current Item + * @uses $iteratorPosition identify current key + * @uses $iteratorKeys identify current value + */ + public function current() { + return $this->value[$this->iteratorKeys[$this->iteratorPosition]]; + } + + /** + * Get Iterator's current key identified by {@link $iteratorPosition} + * @link http://php.net/manual/en/iterator.key.php + * @return string key of the current Item + * @uses $iteratorPosition identify current key + * @uses $iteratorKeys identify current value + */ + public function key() { + return $this->iteratorKeys[$this->iteratorPosition]; + } + + /** + * Increment {@link $iteratorPosition} to address next {@see CFType} + * @link http://php.net/manual/en/iterator.next.php + * @return void + * @uses $iteratorPosition increment by 1 + */ + public function next() { + $this->iteratorPosition++; + } + + /** + * Test if {@link $iteratorPosition} addresses a valid element of {@link $value} + * @link http://php.net/manual/en/iterator.valid.php + * @return boolean true if current position is valid, false else + * @uses $iteratorPosition test if within {@link $iteratorKeys} + * @uses $iteratorPosition test if within {@link $value} + */ + public function valid() { + return isset($this->iteratorKeys[$this->iteratorPosition]) && isset($this->value[$this->iteratorKeys[$this->iteratorPosition]]); + } + +} + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/classes/plist/IOException.php b/Tools/projectGenerator/classes/plist/IOException.php new file mode 100644 index 000000000..991855394 --- /dev/null +++ b/Tools/projectGenerator/classes/plist/IOException.php @@ -0,0 +1,99 @@ + + * @author Christian Kruse + * @package plist + * @version $Id$ + */ + +/** + * Basic Input / Output Exception + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + */ +class IOException extends Exception { + /** + * Flag telling the File could not be found + */ + const NOT_FOUND = 1; + + /** + * Flag telling the File is not readable + */ + const NOT_READABLE = 2; + + /** + * Flag telling the File is not writable + */ + const NOT_WRITABLE = 3; + + /** + * Flag telling there was a read error + */ + const READ_ERROR = 4; + + /** + * Flag telling there was a read error + */ + const WRITE_ERROR = 5; + + /** + * Create new IOException + * @param string $path Source of the problem + * @param integer $type Type of the problem + */ + public function __construct($path, $type=null) { + parent::__construct( $path, $type ); + } + + /** + * Create new FileNotFound-Exception + * @param string $path Source of the problem + * @return IOException new FileNotFound-Exception + */ + public static function notFound($path) { + return new IOException( $path, self::NOT_FOUND ); + } + + /** + * Create new FileNotReadable-Exception + * @param string $path Source of the problem + * @return IOException new FileNotReadable-Exception + */ + public static function notReadable($path) { + return new IOException( $path, self::NOT_READABLE ); + } + + /** + * Create new FileNotWritable-Exception + * @param string $path Source of the problem + * @return IOException new FileNotWritable-Exception + */ + public static function notWritable($path) { + return new IOException( $path, self::NOT_WRITABLE ); + } + + /** + * Create new ReadError-Exception + * @param string $path Source of the problem + * @return IOException new ReadError-Exception + */ + public static function readError($path) { + return new IOException( $path, self::READ_ERROR ); + } + + /** + * Create new WriteError-Exception + * @param string $path Source of the problem + * @return IOException new WriteError-Exception + */ + public static function writeError($path) { + return new IOException( $path, self::WRITE_ERROR ); + } +} + + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/classes/plist/LICENSE b/Tools/projectGenerator/classes/plist/LICENSE new file mode 100644 index 000000000..5e63f61f0 --- /dev/null +++ b/Tools/projectGenerator/classes/plist/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2009 Christian Kruse, Rodney Rehm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/Tools/projectGenerator/classes/plist/PListException.php b/Tools/projectGenerator/classes/plist/PListException.php new file mode 100644 index 000000000..b738d2382 --- /dev/null +++ b/Tools/projectGenerator/classes/plist/PListException.php @@ -0,0 +1,22 @@ + + * @author Christian Kruse + * @package plist + * @version $Id$ + */ + +/** + * Exception for errors with the PList format + * @author Rodney Rehm + * @author Christian Kruse + * @package plist + */ +class PListException extends Exception { + +} + + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/libs/Torque3D.conf b/Tools/projectGenerator/libs/Torque3D.conf new file mode 100644 index 000000000..7ddc28cef --- /dev/null +++ b/Tools/projectGenerator/libs/Torque3D.conf @@ -0,0 +1,277 @@ + diff --git a/Tools/projectGenerator/libs/WebDeploy.conf b/Tools/projectGenerator/libs/WebDeploy.conf new file mode 100644 index 000000000..b92f21f41 --- /dev/null +++ b/Tools/projectGenerator/libs/WebDeploy.conf @@ -0,0 +1,77 @@ + diff --git a/Tools/projectGenerator/libs/collada_dom.conf b/Tools/projectGenerator/libs/collada_dom.conf new file mode 100644 index 000000000..78ebde006 --- /dev/null +++ b/Tools/projectGenerator/libs/collada_dom.conf @@ -0,0 +1,50 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/convexDecomp.conf b/Tools/projectGenerator/libs/convexDecomp.conf new file mode 100644 index 000000000..4cc356883 --- /dev/null +++ b/Tools/projectGenerator/libs/convexDecomp.conf @@ -0,0 +1,43 @@ + diff --git a/Tools/projectGenerator/libs/d3dx8dll.conf b/Tools/projectGenerator/libs/d3dx8dll.conf new file mode 100644 index 000000000..ff6e8d57c --- /dev/null +++ b/Tools/projectGenerator/libs/d3dx8dll.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/jpeg.conf b/Tools/projectGenerator/libs/jpeg.conf new file mode 100644 index 000000000..d75e8d50f --- /dev/null +++ b/Tools/projectGenerator/libs/jpeg.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/libbullet.conf b/Tools/projectGenerator/libs/libbullet.conf new file mode 100644 index 000000000..faaceb832 --- /dev/null +++ b/Tools/projectGenerator/libs/libbullet.conf @@ -0,0 +1,58 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/libogg.conf b/Tools/projectGenerator/libs/libogg.conf new file mode 100644 index 000000000..21c28a7d9 --- /dev/null +++ b/Tools/projectGenerator/libs/libogg.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/libtheora.conf b/Tools/projectGenerator/libs/libtheora.conf new file mode 100644 index 000000000..99abc0dc3 --- /dev/null +++ b/Tools/projectGenerator/libs/libtheora.conf @@ -0,0 +1,30 @@ + diff --git a/Tools/projectGenerator/libs/libvorbis.conf b/Tools/projectGenerator/libs/libvorbis.conf new file mode 100644 index 000000000..13821738e --- /dev/null +++ b/Tools/projectGenerator/libs/libvorbis.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/mng.conf b/Tools/projectGenerator/libs/mng.conf new file mode 100644 index 000000000..b00ecd9d5 --- /dev/null +++ b/Tools/projectGenerator/libs/mng.conf @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/nxCharacter.conf b/Tools/projectGenerator/libs/nxCharacter.conf new file mode 100644 index 000000000..18698d65b --- /dev/null +++ b/Tools/projectGenerator/libs/nxCharacter.conf @@ -0,0 +1,30 @@ + diff --git a/Tools/projectGenerator/libs/nxuStream.conf b/Tools/projectGenerator/libs/nxuStream.conf new file mode 100644 index 000000000..d57162ac4 --- /dev/null +++ b/Tools/projectGenerator/libs/nxuStream.conf @@ -0,0 +1,30 @@ + diff --git a/Tools/projectGenerator/libs/opcode.conf b/Tools/projectGenerator/libs/opcode.conf new file mode 100644 index 000000000..3d19d61fb --- /dev/null +++ b/Tools/projectGenerator/libs/opcode.conf @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/pcre.conf b/Tools/projectGenerator/libs/pcre.conf new file mode 100644 index 000000000..62b315fac --- /dev/null +++ b/Tools/projectGenerator/libs/pcre.conf @@ -0,0 +1,38 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/png.conf b/Tools/projectGenerator/libs/png.conf new file mode 100644 index 000000000..1f73fd53b --- /dev/null +++ b/Tools/projectGenerator/libs/png.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/squish.conf b/Tools/projectGenerator/libs/squish.conf new file mode 100644 index 000000000..8c5964a1b --- /dev/null +++ b/Tools/projectGenerator/libs/squish.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/tinyxml.conf b/Tools/projectGenerator/libs/tinyxml.conf new file mode 100644 index 000000000..6c6f266bd --- /dev/null +++ b/Tools/projectGenerator/libs/tinyxml.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/ungif.conf b/Tools/projectGenerator/libs/ungif.conf new file mode 100644 index 000000000..13238ac02 --- /dev/null +++ b/Tools/projectGenerator/libs/ungif.conf @@ -0,0 +1,32 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/libs/zlib.conf b/Tools/projectGenerator/libs/zlib.conf new file mode 100644 index 000000000..9ae66ca57 --- /dev/null +++ b/Tools/projectGenerator/libs/zlib.conf @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/T3D.inc b/Tools/projectGenerator/modules/T3D.inc new file mode 100644 index 000000000..ae937dbaf --- /dev/null +++ b/Tools/projectGenerator/modules/T3D.inc @@ -0,0 +1,92 @@ + diff --git a/Tools/projectGenerator/modules/Torque3D.inc b/Tools/projectGenerator/modules/Torque3D.inc new file mode 100644 index 000000000..d8e66fbfa --- /dev/null +++ b/Tools/projectGenerator/modules/Torque3D.inc @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/advancedLighting.inc b/Tools/projectGenerator/modules/advancedLighting.inc new file mode 100644 index 000000000..196dfabaa --- /dev/null +++ b/Tools/projectGenerator/modules/advancedLighting.inc @@ -0,0 +1,46 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/basicLighting.inc b/Tools/projectGenerator/modules/basicLighting.inc new file mode 100644 index 000000000..5b5cc7e11 --- /dev/null +++ b/Tools/projectGenerator/modules/basicLighting.inc @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/bullet.inc b/Tools/projectGenerator/modules/bullet.inc new file mode 100644 index 000000000..1ee4de9d2 --- /dev/null +++ b/Tools/projectGenerator/modules/bullet.inc @@ -0,0 +1,44 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/collada.inc b/Tools/projectGenerator/modules/collada.inc new file mode 100644 index 000000000..0155cec58 --- /dev/null +++ b/Tools/projectGenerator/modules/collada.inc @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/core.inc b/Tools/projectGenerator/modules/core.inc new file mode 100644 index 000000000..0fa0d5000 --- /dev/null +++ b/Tools/projectGenerator/modules/core.inc @@ -0,0 +1,199 @@ + diff --git a/Tools/projectGenerator/modules/d3dx8dll.inc b/Tools/projectGenerator/modules/d3dx8dll.inc new file mode 100644 index 000000000..007464693 --- /dev/null +++ b/Tools/projectGenerator/modules/d3dx8dll.inc @@ -0,0 +1,41 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/dsound.inc b/Tools/projectGenerator/modules/dsound.inc new file mode 100644 index 000000000..178d910ff --- /dev/null +++ b/Tools/projectGenerator/modules/dsound.inc @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/fmod.inc b/Tools/projectGenerator/modules/fmod.inc new file mode 100644 index 000000000..7fecc2fce --- /dev/null +++ b/Tools/projectGenerator/modules/fmod.inc @@ -0,0 +1,77 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/jpeg.inc b/Tools/projectGenerator/modules/jpeg.inc new file mode 100644 index 000000000..1fe72955b --- /dev/null +++ b/Tools/projectGenerator/modules/jpeg.inc @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/libode.inc b/Tools/projectGenerator/modules/libode.inc new file mode 100644 index 000000000..a71a5d629 --- /dev/null +++ b/Tools/projectGenerator/modules/libode.inc @@ -0,0 +1,36 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/libogg.inc b/Tools/projectGenerator/modules/libogg.inc new file mode 100644 index 000000000..02977f602 --- /dev/null +++ b/Tools/projectGenerator/modules/libogg.inc @@ -0,0 +1,29 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/libtheora.inc b/Tools/projectGenerator/modules/libtheora.inc new file mode 100644 index 000000000..dfba45845 --- /dev/null +++ b/Tools/projectGenerator/modules/libtheora.inc @@ -0,0 +1,58 @@ + diff --git a/Tools/projectGenerator/modules/libvorbis.inc b/Tools/projectGenerator/modules/libvorbis.inc new file mode 100644 index 000000000..548266f7c --- /dev/null +++ b/Tools/projectGenerator/modules/libvorbis.inc @@ -0,0 +1,48 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/mng.inc b/Tools/projectGenerator/modules/mng.inc new file mode 100644 index 000000000..235c610ac --- /dev/null +++ b/Tools/projectGenerator/modules/mng.inc @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/nxCharacter.inc b/Tools/projectGenerator/modules/nxCharacter.inc new file mode 100644 index 000000000..4ebb17c87 --- /dev/null +++ b/Tools/projectGenerator/modules/nxCharacter.inc @@ -0,0 +1,45 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/nxuStream.inc b/Tools/projectGenerator/modules/nxuStream.inc new file mode 100644 index 000000000..6ad237b59 --- /dev/null +++ b/Tools/projectGenerator/modules/nxuStream.inc @@ -0,0 +1,43 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/opcode.inc b/Tools/projectGenerator/modules/opcode.inc new file mode 100644 index 000000000..399b6a47b --- /dev/null +++ b/Tools/projectGenerator/modules/opcode.inc @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/openal.inc b/Tools/projectGenerator/modules/openal.inc new file mode 100644 index 000000000..d3356b55f --- /dev/null +++ b/Tools/projectGenerator/modules/openal.inc @@ -0,0 +1,32 @@ + diff --git a/Tools/projectGenerator/modules/pestTimer.inc b/Tools/projectGenerator/modules/pestTimer.inc new file mode 100644 index 000000000..d1f2c0e40 --- /dev/null +++ b/Tools/projectGenerator/modules/pestTimer.inc @@ -0,0 +1,30 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/physX.inc b/Tools/projectGenerator/modules/physX.inc new file mode 100644 index 000000000..548c2a2cf --- /dev/null +++ b/Tools/projectGenerator/modules/physX.inc @@ -0,0 +1,107 @@ + diff --git a/Tools/projectGenerator/modules/png.inc b/Tools/projectGenerator/modules/png.inc new file mode 100644 index 000000000..4165225e3 --- /dev/null +++ b/Tools/projectGenerator/modules/png.inc @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/squish.inc b/Tools/projectGenerator/modules/squish.inc new file mode 100644 index 000000000..0fb8f28e6 --- /dev/null +++ b/Tools/projectGenerator/modules/squish.inc @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/theora.inc b/Tools/projectGenerator/modules/theora.inc new file mode 100644 index 000000000..13f983b2b --- /dev/null +++ b/Tools/projectGenerator/modules/theora.inc @@ -0,0 +1,31 @@ + diff --git a/Tools/projectGenerator/modules/tinyxml.inc b/Tools/projectGenerator/modules/tinyxml.inc new file mode 100644 index 000000000..99b341291 --- /dev/null +++ b/Tools/projectGenerator/modules/tinyxml.inc @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/tools.inc b/Tools/projectGenerator/modules/tools.inc new file mode 100644 index 000000000..d88092a32 --- /dev/null +++ b/Tools/projectGenerator/modules/tools.inc @@ -0,0 +1,39 @@ + diff --git a/Tools/projectGenerator/modules/ungif.inc b/Tools/projectGenerator/modules/ungif.inc new file mode 100644 index 000000000..25f466493 --- /dev/null +++ b/Tools/projectGenerator/modules/ungif.inc @@ -0,0 +1,33 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/vorbis.inc b/Tools/projectGenerator/modules/vorbis.inc new file mode 100644 index 000000000..3a95d6e9b --- /dev/null +++ b/Tools/projectGenerator/modules/vorbis.inc @@ -0,0 +1,26 @@ + diff --git a/Tools/projectGenerator/modules/webDeploy.inc b/Tools/projectGenerator/modules/webDeploy.inc new file mode 100644 index 000000000..d371e8da4 --- /dev/null +++ b/Tools/projectGenerator/modules/webDeploy.inc @@ -0,0 +1,30 @@ + diff --git a/Tools/projectGenerator/modules/xaudio.inc b/Tools/projectGenerator/modules/xaudio.inc new file mode 100644 index 000000000..149d3e600 --- /dev/null +++ b/Tools/projectGenerator/modules/xaudio.inc @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/modules/zlib.inc b/Tools/projectGenerator/modules/zlib.inc new file mode 100644 index 000000000..5713bf5ca --- /dev/null +++ b/Tools/projectGenerator/modules/zlib.inc @@ -0,0 +1,34 @@ + \ No newline at end of file diff --git a/Tools/projectGenerator/newProject.php b/Tools/projectGenerator/newProject.php new file mode 100644 index 000000000..6618d8cfe --- /dev/null +++ b/Tools/projectGenerator/newProject.php @@ -0,0 +1,216 @@ +read() ) ) + { + // Read through exclude list. If the current directory is on it, skip it + $skip = false; + foreach($exclude as $exclFile) + { + if($entry == $exclFile) + { + $skip = true; + continue; + } + } + + if ( $entry == '.' || $entry == '..' || $skip ) + continue; + + $entryFullPath = $source . '/' . $entry; + if ( is_dir( $entryFullPath ) ) + { + copyDir( $entryFullPath, $target . '/' . $entry, $exclude ); + continue; + } + + copy( $entryFullPath, $target . '/' . $entry ); + echo("Copying " . $entry . " to " . $target . "/\n"); + } + + $dirRef->close(); + } + else + copy( $source, $target ); +} + +// Function taken from PHP.net +function rm_recursive($filepath) +{ + if (is_dir($filepath) && !is_link($filepath)) + { + if ($dirRef = opendir($filepath)) + { + while (($curfile = readdir($dirRef)) !== false) + { + if ($curfile == '.' || $curfile == '..') + continue; + + if (!rm_recursive($filepath.'/'.$curfile)) + throw new Exception($filepath.'/'.$curfile.' could not be deleted.'); + } + + closedir($dirRef); + } + + return rmdir($filepath); + } + + return unlink($filepath); +} + +// Replaces all instances of the given text string from the given file +function ReplaceTextInFile($file, $string, $replace) +{ + $buf = ""; + $confg = file($file); + + foreach ($confg as $line) + { + $line = str_replace($string, $replace, $line); + $buf .= $line; + } + + $confg = fopen($file, "w"); + fwrite($confg, $buf); + fclose($confg); +} + +// Flag that notes whether a simple (non-fatal) error has occurred +$withError = false; + +// Minimum number of passed arguments is 3 +if($argc < 4) + exit("\nError! Invalid number of arguments! Correct format is Project_Name Torque_Root Project_Destination_Path (optional -O overwrite existing files)\n"); +// If there are 5 args and the last one isn't the override flag, it's a fatal error +else if($argc == 5 && $argv[4] != "-O") + exit("\nInvalid argument of $argv[4]! Should be -O (optional overwrite existing files flag)\n"); + +// Define our main working paths +$torqueDir = $argv[2]; +$newPath = $argv[3] . "/".$argv[1] . "/"; +$templPath = $torqueDir . "/Templates/Full/"; + +// Aesthetics...php doesn't care +$newPath = str_replace("//", "/", $newPath); +$templPath = str_replace("//", "/", $templPath); + +// Check if template path exists (ie user didn't do something wrong) +if(is_dir($templPath)) +{ + // If the destination path doesn't exist, make it + if(!is_dir($argv[3])) + mkdir($argv[3], 0777, true); + + // If the project folder exists, check for -O + if(is_dir($newPath)) + { + //If there's no -O, we exit out + if($argv[4] != "-O") + exit("\nProject folder already exists! Use -O as 4th argument is you wish to overwrite"); + + // Otherwise we delete the other .exe and .torsion as they won't otherwise be overwritten + else + { + if(!unlink($newPath . "game/" . $argv[1] . ".exe") || + !unlink($newPath . "game/" . $argv[1] . ".torsion")) + { + echo("\nError deleting old files " . $argv[1] . ".exe and " . $argv[1] . ".torsion\n"); + $withError = true; + } + } + } + + // Read directory exclusion list from file (most likely provided by GUI prompt) + $exclude = file($templPath . "exclude.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + + // By default exclude .svn, config, and buildFiles + if($exclude == false) + { + $exclude = array(".svn", "Link"); + } + + else + { + $exclude[] = ".svn"; + $exclude[] = "Link"; + } + + copyDir($templPath, $newPath, $exclude); +} + +// If the given template directory does not exist, we exit +else{ + exit("\nTemplate directory does not exist at $templPath!"); +} + +//Replace references to template +ReplaceTextInFile($newPath . "buildFiles/config/project.conf", "Full", $argv[1]); +ReplaceTextInFile($newPath . "buildFiles/config/project.360.conf", "Full", $argv[1]); +ReplaceTextInFile($newPath . "buildFiles/config/project.mac.conf", "Full", $argv[1]); +ReplaceTextInFile($newPath . "game/Template.torsion", "Full", $argv[1]); +ReplaceTextInFile($newPath . "game/main.cs", "Full", $argv[1]); +ReplaceTextInFile($newPath . "source/torqueConfig.h", "Full", $argv[1]); + +//Rename the executable and the torsion project file +if(!rename($newPath . "game/Full.exe", $newPath . "game/" . $argv[1] . ".exe")) +{ + echo("\n\nCould not rename Full.exe! You may need to rename manually\n"); + $withError = true; +} + +if(!rename($newPath . "game/Full.torsion", $newPath . "game/" . $argv[1] . ".torsion")) +{ + echo("\n\nCould not rename Full.torsion! You may need to rename manually\n"); + $withError = true; +} + +chdir($newPath); + +// Generate the projects and solutions using the generateProjects.bat +// We don't hand in the $torqueDir if our output path is in the Torque folders +// Probably should make this smarter so that it can handle directories that +// are in the the Torque folder but are not at the same level as GameExamples and Projects +if (stristr($newPath, $torqueDir)) + passthru("generateProjects.bat noPause"); +else + passthru("generateProjects.bat noPause $torqueDir"); + +// If there wasn't an error, print happy message +if(!$withError) + echo("\nProject creation complete!\nYou can find your new project at $newPath."); +// If there was, print ultra mega sad message +else + echo("\nProject creation completed, however there were some errors. Please verify that your new project is correct.\nYou can find your new project at $newPath."); + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/projectGenUtils.inc b/Tools/projectGenerator/projectGenUtils.inc new file mode 100644 index 000000000..e5d066495 --- /dev/null +++ b/Tools/projectGenerator/projectGenUtils.inc @@ -0,0 +1,490 @@ + 0 ) + Generator::addProjectDefines( $args ); + else + echo( "addProjectDefines() - no arguments passed!" ); +} + +function setProjectGUID( $guid ) +{ + Generator::setProjectGUID( $guid ); +} + +function setProjectModuleDefinitionFile( $mdef ) +{ + Generator::setProjectModuleDefinitionFile( $mdef ); +} + + +function addProjectLibDir( $dir ) +{ + Generator::addProjectLibDir( $dir ); +} + +function addProjectLibInput( $lib_name ) +{ + Generator::addProjectLibInput( $lib_name ); +} + +function addProjectDependency( $pd ) +{ + Generator::addProjectDependency( $pd ); +} + +function removeProjectDependency( $pd ) +{ + Generator::removeProjectDependency( $pd ); +} + +function addProjectReference( $refName, $version = "" ) +{ + Generator::addProjectReference( $refName, $version ); +} + +// disable a specific project compiler warning +function disableProjectWarning( $warning ) +{ + Generator::disableProjectWarning( $warning ); +} + + +function setGameProjectName($name) +{ + Generator::setGameProjectName($name); +} + +function getGameProjectName() +{ + return Generator::getGameProjectName(); +} + +function setToolBuild($tb) +{ + Generator::setToolBuild($tb); +} + +function getToolBuild() +{ + return Generator::getToolBuild(); +} + +function setWatermarkBuild($wb) +{ + Generator::setWatermarkBuild($wb); +} + +function getWatermarkBuild() +{ + return Generator::getWatermarkBuild(); +} + +function setPurchaseScreenBuild($psb) +{ + Generator::setPurchaseScreenBuild($psb); +} + +function getPurchaseScreenBuild() +{ + return Generator::getPurchaseScreenBuild(); +} + +function setDemoBuild($db) +{ + Generator::setDemoBuild($db); +} + +function getDemoBuild() +{ + return Generator::getDemoBuild(); +} + +function setObjectLimitBuild($olb) +{ + Generator::setObjectLimitBuild($olb); +} + +function getObjectLimitBuild() +{ + return Generator::getObjectLimitBuild(); +} + +function setTimeOutBuild($tob) +{ + Generator::setTimeOutBuild($tob); +} + +function getTimeOutBuild() +{ + return Generator::getTimeOutBuild(); +} + +function inProjectConfig() +{ + return Generator::inProjectConfig(); +} + +// On Windows, 1 - Console, 2 - Windows +function setProjectSubSystem( $subSystem ) +{ + Generator::setProjectSubSystem( $subSystem ); +} + +// Sets whether to use /MT or /MD code generation/runtime on Windows +// /MD plays better with multiple dynamic libraries in a project (and with certain libraries (like Qt) +// /MD also generates smaller binaries as the runtime isn't included in each module, memory is handled consistently, etc +// You must include or install via the redistributable package the appropriate VS runtime for end users. +function setDLLRuntime ($val) +{ + Generator::setDLLRuntime( $val ); +} + +//-------------------------------------------------------------------------------- UTIL + +// Some versions of PHP4 are unable to recusively create directories. +// The version of PHP that is distributed with Mac OS 10.4 suffers from this. +function mkdir_r($path, $mode) +{ + if( @mkdir( $path, $mode ) or file_exists( $path ) ) + return true; + + return ( mkdir_r( dirname( $path ), $mode ) and mkdir( $path, $mode ) ); +} + +// This is used inside an if statement in the smarty templates +function dontCompile( $string, $output ) +{ + // Skip marking header files to be excluded from the + // build. It confuses VS2010 and it will not put the + // file into the correct filter folder. + // + if ( preg_match( '#^.*\.(h|hpp|hh|inc)$#i', $string ) ) + return false; + + if( !is_array( $output->dont_compile_patterns ) ) + return false; + + foreach( $output->dont_compile_patterns as $pattern ) + if( preg_match( $pattern, $string ) ) + return true; + + return false; +} + + +/// Generates and returns a randomly generated uuid in the form: +/// +/// {xxxxxxxx-xxxx-4xxx-Yxxx-xxxxxxxxxxxx} +/// +/// Where Y is either 8, 9, A, or B. This is known as +/// a v4 UUID. See... +/// +/// http://en.wikipedia.org/wiki/Universally_Unique_Identifier#Version_4_.28random.29 +/// +function gen_uuid() +{ + return sprintf( '{%04x%04x-%04x-%04x-%04x-%04x%04x%04x}', + // 32 bits for "time_low" + mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), + + // 16 bits for "time_mid" + mt_rand( 0, 0xffff ), + + // 16 bits for "time_hi_and_version", + // four most significant bits holds version number 4 + mt_rand( 0, 0x0fff ) | 0x4000, + + // 16 bits, 8 bits for "clk_seq_hi_res", + // 8 bits for "clk_seq_low", + // two most significant bits holds zero and one for variant DCE1.1 + mt_rand( 0, 0x3fff ) | 0x8000, + + // 48 bits for "node" + mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ) + ); +} + +?> diff --git a/Tools/projectGenerator/projectGenerator.php b/Tools/projectGenerator/projectGenerator.php new file mode 100644 index 000000000..103fa536e --- /dev/null +++ b/Tools/projectGenerator/projectGenerator.php @@ -0,0 +1,92 @@ +template_dir = $g_cwd . "/templates"; +$tpl->compile_dir = $g_cwd . "/templates_c"; + +$tpl->clear_all_cache(); + +// By default we assume that the root of the Torque SDK +// is located two folders up from the CWD. That is unless +// another path is passed in the command line. +$torqueRoot = "../.."; +if ( $argc >= 3 ) + $torqueRoot = str_replace( "\\", "/", $argv[2] ); + +// Kick off the generator +Generator::init( $torqueRoot ); + +// Ready to read our config file. +echo( " - Loading config file " . realpath($argv[1])."\n" ); + +require( $argv[ 1 ] ); + +// Generate all projects +Generator::generateProjects( $tpl ); + +// Now the solutions (if any) +$tpl->clear_all_cache(); + +Generator::generateSolutions( $tpl ); + +// finally write out the sample.html for web deployment (if any) +WebPlugin::writeSampleHtml(); + +exit; +?> diff --git a/Tools/projectGenerator/smarty/Config_File.class.php b/Tools/projectGenerator/smarty/Config_File.class.php new file mode 100644 index 000000000..3d7c1b493 --- /dev/null +++ b/Tools/projectGenerator/smarty/Config_File.class.php @@ -0,0 +1,389 @@ + + * @access public + * @package Smarty + */ + +/* $Id: Config_File.class.php,v 1.88 2007/03/06 10:40:06 messju Exp $ */ + +/** + * Config file reading class + * @package Smarty + */ +class Config_File { + /**#@+ + * Options + * @var boolean + */ + /** + * Controls whether variables with the same name overwrite each other. + */ + var $overwrite = true; + + /** + * Controls whether config values of on/true/yes and off/false/no get + * converted to boolean values automatically. + */ + var $booleanize = true; + + /** + * Controls whether hidden config sections/vars are read from the file. + */ + var $read_hidden = true; + + /** + * Controls whether or not to fix mac or dos formatted newlines. + * If set to true, \r or \r\n will be changed to \n. + */ + var $fix_newlines = true; + /**#@-*/ + + /** @access private */ + var $_config_path = ""; + var $_config_data = array(); + /**#@-*/ + + /** + * Constructs a new config file class. + * + * @param string $config_path (optional) path to the config files + */ + function Config_File($config_path = NULL) + { + if (isset($config_path)) + $this->set_path($config_path); + } + + + /** + * Set the path where configuration files can be found. + * + * @param string $config_path path to the config files + */ + function set_path($config_path) + { + if (!empty($config_path)) { + if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) { + $this->_trigger_error_msg("Bad config file path '$config_path'"); + return; + } + if(substr($config_path, -1) != DIRECTORY_SEPARATOR) { + $config_path .= DIRECTORY_SEPARATOR; + } + + $this->_config_path = $config_path; + } + } + + + /** + * Retrieves config info based on the file, section, and variable name. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @param string $var_name (optional) variable to get info for + * @return string|array a value or array of values + */ + function get($file_name, $section_name = NULL, $var_name = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) + $this->load_file($file_name, false); + } + + if (!empty($var_name)) { + if (empty($section_name)) { + return $this->_config_data[$file_name]["vars"][$var_name]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name])) + return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]; + else + return array(); + } + } else { + if (empty($section_name)) { + return (array)$this->_config_data[$file_name]["vars"]; + } else { + if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"])) + return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"]; + else + return array(); + } + } + } + + + /** + * Retrieves config info based on the key. + * + * @param $file_name string config key (filename/section/var) + * @return string|array same as get() + * @uses get() retrieves information from config file and returns it + */ + function &get_key($config_key) + { + list($file_name, $section_name, $var_name) = explode('/', $config_key, 3); + $result = &$this->get($file_name, $section_name, $var_name); + return $result; + } + + /** + * Get all loaded config file names. + * + * @return array an array of loaded config file names + */ + function get_file_names() + { + return array_keys($this->_config_data); + } + + + /** + * Get all section names from a loaded file. + * + * @param string $file_name config file to get section names from + * @return array an array of section names from the specified file + */ + function get_section_names($file_name) + { + $file_name = $this->_config_path . $file_name; + if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + return array_keys($this->_config_data[$file_name]["sections"]); + } + + + /** + * Get all global or section variable names. + * + * @param string $file_name config file to get info for + * @param string $section_name (optional) section to get info for + * @return array an array of variables names from the specified file/section + */ + function get_var_names($file_name, $section = NULL) + { + if (empty($file_name)) { + $this->_trigger_error_msg('Empty config file name'); + return; + } else if (!isset($this->_config_data[$file_name])) { + $this->_trigger_error_msg("Unknown config file '$file_name'"); + return; + } + + if (empty($section)) + return array_keys($this->_config_data[$file_name]["vars"]); + else + return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]); + } + + + /** + * Clear loaded config data for a certain file or all files. + * + * @param string $file_name file to clear config data for + */ + function clear($file_name = NULL) + { + if ($file_name === NULL) + $this->_config_data = array(); + else if (isset($this->_config_data[$file_name])) + $this->_config_data[$file_name] = array(); + } + + + /** + * Load a configuration file manually. + * + * @param string $file_name file name to load + * @param boolean $prepend_path whether current config path should be + * prepended to the filename + */ + function load_file($file_name, $prepend_path = true) + { + if ($prepend_path && $this->_config_path != "") + $config_file = $this->_config_path . $file_name; + else + $config_file = $file_name; + + ini_set('track_errors', true); + $fp = @fopen($config_file, "r"); + if (!is_resource($fp)) { + $this->_trigger_error_msg("Could not open config file '$config_file'"); + return false; + } + + $contents = ($size = filesize($config_file)) ? fread($fp, $size) : ''; + fclose($fp); + + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * Store the contents of a file manually. + * + * @param string $config_file file name of the related contents + * @param string $contents the file-contents to parse + */ + function set_file_contents($config_file, $contents) + { + $this->_config_data[$config_file] = $this->parse_contents($contents); + return true; + } + + /** + * parse the source of a configuration file manually. + * + * @param string $contents the file-contents to parse + */ + function parse_contents($contents) + { + if($this->fix_newlines) { + // fix mac/dos formatted newlines + $contents = preg_replace('!\r\n?!', "\n", $contents); + } + + $config_data = array(); + $config_data['sections'] = array(); + $config_data['vars'] = array(); + + /* reference to fill with data */ + $vars =& $config_data['vars']; + + /* parse file line by line */ + preg_match_all('!^.*\r?\n?!m', $contents, $match); + $lines = $match[0]; + for ($i=0, $count=count($lines); $i<$count; $i++) { + $line = $lines[$i]; + if (empty($line)) continue; + + if ( substr($line, 0, 1) == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) { + /* section found */ + if (substr($match[1], 0, 1) == '.') { + /* hidden section */ + if ($this->read_hidden) { + $section_name = substr($match[1], 1); + } else { + /* break reference to $vars to ignore hidden section */ + unset($vars); + $vars = array(); + continue; + } + } else { + $section_name = $match[1]; + } + if (!isset($config_data['sections'][$section_name])) + $config_data['sections'][$section_name] = array('vars' => array()); + $vars =& $config_data['sections'][$section_name]['vars']; + continue; + } + + if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) { + /* variable found */ + $var_name = rtrim($match[1]); + if (strpos($match[2], '"""') === 0) { + /* handle multiline-value */ + $lines[$i] = substr($match[2], 3); + $var_value = ''; + while ($i<$count) { + if (($pos = strpos($lines[$i], '"""')) === false) { + $var_value .= $lines[$i++]; + } else { + /* end of multiline-value */ + $var_value .= substr($lines[$i], 0, $pos); + break; + } + } + $booleanize = false; + + } else { + /* handle simple value */ + $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2])); + $booleanize = $this->booleanize; + + } + $this->_set_config_var($vars, $var_name, $var_value, $booleanize); + } + /* else unparsable line / means it is a comment / means ignore it */ + } + return $config_data; + } + + /**#@+ @access private */ + /** + * @param array &$container + * @param string $var_name + * @param mixed $var_value + * @param boolean $booleanize determines whether $var_value is converted to + * to true/false + */ + function _set_config_var(&$container, $var_name, $var_value, $booleanize) + { + if (substr($var_name, 0, 1) == '.') { + if (!$this->read_hidden) + return; + else + $var_name = substr($var_name, 1); + } + + if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) { + $this->_trigger_error_msg("Bad variable name '$var_name'"); + return; + } + + if ($booleanize) { + if (preg_match("/^(on|true|yes)$/i", $var_value)) + $var_value = true; + else if (preg_match("/^(off|false|no)$/i", $var_value)) + $var_value = false; + } + + if (!isset($container[$var_name]) || $this->overwrite) + $container[$var_name] = $var_value; + else { + settype($container[$var_name], 'array'); + $container[$var_name][] = $var_value; + } + } + + /** + * @uses trigger_error() creates a PHP warning/error + * @param string $error_msg + * @param integer $error_type one of + */ + function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Config_File error: $error_msg", $error_type); + } + /**#@-*/ +} + +?> diff --git a/Tools/projectGenerator/smarty/Smarty.class.php b/Tools/projectGenerator/smarty/Smarty.class.php new file mode 100644 index 000000000..f05e0dade --- /dev/null +++ b/Tools/projectGenerator/smarty/Smarty.class.php @@ -0,0 +1,1944 @@ + + * @author Andrei Zmievski + * @package Smarty + * @version 2.6.18 + */ + +/* $Id: Smarty.class.php,v 1.528 2007/03/06 10:40:06 messju Exp $ */ + +/** + * DIR_SEP isn't used anymore, but third party apps might + */ +if(!defined('DIR_SEP')) { + define('DIR_SEP', DIRECTORY_SEPARATOR); +} + +/** + * set SMARTY_DIR to absolute path to Smarty library files. + * if not defined, include_path will be used. Sets SMARTY_DIR only if user + * application has not already defined it. + */ + +if (!defined('SMARTY_DIR')) { + define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); +} + +if (!defined('SMARTY_CORE_DIR')) { + define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR); +} + +define('SMARTY_PHP_PASSTHRU', 0); +define('SMARTY_PHP_QUOTE', 1); +define('SMARTY_PHP_REMOVE', 2); +define('SMARTY_PHP_ALLOW', 3); + +/** + * @package Smarty + */ +class Smarty +{ + /**#@+ + * Smarty Configuration Section + */ + + /** + * The name of the directory where templates are located. + * + * @var string + */ + var $template_dir = 'templates'; + + /** + * The directory where compiled templates are located. + * + * @var string + */ + var $compile_dir = 'templates_c'; + + /** + * The directory where config files are located. + * + * @var string + */ + var $config_dir = 'configs'; + + /** + * An array of directories searched for plugins. + * + * @var array + */ + var $plugins_dir = array('plugins'); + + /** + * If debugging is enabled, a debug console window will display + * when the page loads (make sure your browser allows unrequested + * popup windows) + * + * @var boolean + */ + var $debugging = false; + + /** + * When set, smarty does uses this value as error_reporting-level. + * + * @var boolean + */ + var $error_reporting = null; + + /** + * This is the path to the debug console template. If not set, + * the default one will be used. + * + * @var string + */ + var $debug_tpl = ''; + + /** + * This determines if debugging is enable-able from the browser. + *
    + *
  • NONE => no debugging control allowed
  • + *
  • URL => enable debugging when SMARTY_DEBUG is found in the URL.
  • + *
+ * @link http://www.foo.dom/index.php?SMARTY_DEBUG + * @var string + */ + var $debugging_ctrl = 'NONE'; + + /** + * This tells Smarty whether to check for recompiling or not. Recompiling + * does not need to happen unless a template or config file is changed. + * Typically you enable this during development, and disable for + * production. + * + * @var boolean + */ + var $compile_check = true; + + /** + * This forces templates to compile every time. Useful for development + * or debugging. + * + * @var boolean + */ + var $force_compile = false; + + /** + * This enables template caching. + *
    + *
  • 0 = no caching
  • + *
  • 1 = use class cache_lifetime value
  • + *
  • 2 = use cache_lifetime in cache file
  • + *
+ * @var integer + */ + var $caching = 0; + + /** + * The name of the directory for cache files. + * + * @var string + */ + var $cache_dir = 'cache'; + + /** + * This is the number of seconds cached content will persist. + *
    + *
  • 0 = always regenerate cache
  • + *
  • -1 = never expires
  • + *
+ * + * @var integer + */ + var $cache_lifetime = 3600; + + /** + * Only used when $caching is enabled. If true, then If-Modified-Since headers + * are respected with cached content, and appropriate HTTP headers are sent. + * This way repeated hits to a cached page do not send the entire page to the + * client every time. + * + * @var boolean + */ + var $cache_modified_check = false; + + /** + * This determines how Smarty handles "" tags in templates. + * possible values: + *
    + *
  • SMARTY_PHP_PASSTHRU -> print tags as plain text
  • + *
  • SMARTY_PHP_QUOTE -> escape tags as entities
  • + *
  • SMARTY_PHP_REMOVE -> remove php tags
  • + *
  • SMARTY_PHP_ALLOW -> execute php tags
  • + *
+ * + * @var integer + */ + var $php_handling = SMARTY_PHP_PASSTHRU; + + /** + * This enables template security. When enabled, many things are restricted + * in the templates that normally would go unchecked. This is useful when + * untrusted parties are editing templates and you want a reasonable level + * of security. (no direct execution of PHP in templates for example) + * + * @var boolean + */ + var $security = false; + + /** + * This is the list of template directories that are considered secure. This + * is used only if {@link $security} is enabled. One directory per array + * element. {@link $template_dir} is in this list implicitly. + * + * @var array + */ + var $secure_dir = array(); + + /** + * These are the security settings for Smarty. They are used only when + * {@link $security} is enabled. + * + * @var array + */ + var $security_settings = array( + 'PHP_HANDLING' => false, + 'IF_FUNCS' => array('array', 'list', + 'isset', 'empty', + 'count', 'sizeof', + 'in_array', 'is_array', + 'true', 'false', 'null'), + 'INCLUDE_ANY' => false, + 'PHP_TAGS' => false, + 'MODIFIER_FUNCS' => array('count'), + 'ALLOW_CONSTANTS' => false + ); + + /** + * This is an array of directories where trusted php scripts reside. + * {@link $security} is disabled during their inclusion/execution. + * + * @var array + */ + var $trusted_dir = array(); + + /** + * The left delimiter used for the template tags. + * + * @var string + */ + var $left_delimiter = '{'; + + /** + * The right delimiter used for the template tags. + * + * @var string + */ + var $right_delimiter = '}'; + + /** + * The order in which request variables are registered, similar to + * variables_order in php.ini E = Environment, G = GET, P = POST, + * C = Cookies, S = Server + * + * @var string + */ + var $request_vars_order = 'EGPCS'; + + /** + * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false) + * are uses as request-vars or $_*[]-vars. note: if + * request_use_auto_globals is true, then $request_vars_order has + * no effect, but the php-ini-value "gpc_order" + * + * @var boolean + */ + var $request_use_auto_globals = true; + + /** + * Set this if you want different sets of compiled files for the same + * templates. This is useful for things like different languages. + * Instead of creating separate sets of templates per language, you + * set different compile_ids like 'en' and 'de'. + * + * @var string + */ + var $compile_id = null; + + /** + * This tells Smarty whether or not to use sub dirs in the cache/ and + * templates_c/ directories. sub directories better organized, but + * may not work well with PHP safe mode enabled. + * + * @var boolean + * + */ + var $use_sub_dirs = false; + + /** + * This is a list of the modifiers to apply to all template variables. + * Put each modifier in a separate array element in the order you want + * them applied. example: array('escape:"htmlall"'); + * + * @var array + */ + var $default_modifiers = array(); + + /** + * This is the resource type to be used when not specified + * at the beginning of the resource path. examples: + * $smarty->display('file:index.tpl'); + * $smarty->display('db:index.tpl'); + * $smarty->display('index.tpl'); // will use default resource type + * {include file="file:index.tpl"} + * {include file="db:index.tpl"} + * {include file="index.tpl"} {* will use default resource type *} + * + * @var array + */ + var $default_resource_type = 'file'; + + /** + * The function used for cache file handling. If not set, built-in caching is used. + * + * @var null|string function name + */ + var $cache_handler_func = null; + + /** + * This indicates which filters are automatically loaded into Smarty. + * + * @var array array of filter names + */ + var $autoload_filters = array(); + + /**#@+ + * @var boolean + */ + /** + * This tells if config file vars of the same name overwrite each other or not. + * if disabled, same name variables are accumulated in an array. + */ + var $config_overwrite = true; + + /** + * This tells whether or not to automatically booleanize config file variables. + * If enabled, then the strings "on", "true", and "yes" are treated as boolean + * true, and "off", "false" and "no" are treated as boolean false. + */ + var $config_booleanize = true; + + /** + * This tells whether hidden sections [.foobar] are readable from the + * tempalates or not. Normally you would never allow this since that is + * the point behind hidden sections: the application can access them, but + * the templates cannot. + */ + var $config_read_hidden = false; + + /** + * This tells whether or not automatically fix newlines in config files. + * It basically converts \r (mac) or \r\n (dos) to \n + */ + var $config_fix_newlines = true; + /**#@-*/ + + /** + * If a template cannot be found, this PHP function will be executed. + * Useful for creating templates on-the-fly or other special action. + * + * @var string function name + */ + var $default_template_handler_func = ''; + + /** + * The file that contains the compiler class. This can a full + * pathname, or relative to the php_include path. + * + * @var string + */ + var $compiler_file = 'Smarty_Compiler.class.php'; + + /** + * The class used for compiling templates. + * + * @var string + */ + var $compiler_class = 'Smarty_Compiler'; + + /** + * The class used to load config vars. + * + * @var string + */ + var $config_class = 'Config_File'; + +/**#@+ + * END Smarty Configuration Section + * There should be no need to touch anything below this line. + * @access private + */ + /** + * where assigned template vars are kept + * + * @var array + */ + var $_tpl_vars = array(); + + /** + * stores run-time $smarty.* vars + * + * @var null|array + */ + var $_smarty_vars = null; + + /** + * keeps track of sections + * + * @var array + */ + var $_sections = array(); + + /** + * keeps track of foreach blocks + * + * @var array + */ + var $_foreach = array(); + + /** + * keeps track of tag hierarchy + * + * @var array + */ + var $_tag_stack = array(); + + /** + * configuration object + * + * @var Config_file + */ + var $_conf_obj = null; + + /** + * loaded configuration settings + * + * @var array + */ + var $_config = array(array('vars' => array(), 'files' => array())); + + /** + * md5 checksum of the string 'Smarty' + * + * @var string + */ + var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; + + /** + * Smarty version number + * + * @var string + */ + var $_version = '2.6.18'; + + /** + * current template inclusion depth + * + * @var integer + */ + var $_inclusion_depth = 0; + + /** + * for different compiled templates + * + * @var string + */ + var $_compile_id = null; + + /** + * text in URL to enable debug mode + * + * @var string + */ + var $_smarty_debug_id = 'SMARTY_DEBUG'; + + /** + * debugging information for debug console + * + * @var array + */ + var $_smarty_debug_info = array(); + + /** + * info that makes up a cache file + * + * @var array + */ + var $_cache_info = array(); + + /** + * default file permissions + * + * @var integer + */ + var $_file_perms = 0644; + + /** + * default dir permissions + * + * @var integer + */ + var $_dir_perms = 0771; + + /** + * registered objects + * + * @var array + */ + var $_reg_objects = array(); + + /** + * table keeping track of plugins + * + * @var array + */ + var $_plugins = array( + 'modifier' => array(), + 'function' => array(), + 'block' => array(), + 'compiler' => array(), + 'prefilter' => array(), + 'postfilter' => array(), + 'outputfilter' => array(), + 'resource' => array(), + 'insert' => array()); + + + /** + * cache serials + * + * @var array + */ + var $_cache_serials = array(); + + /** + * name of optional cache include file + * + * @var string + */ + var $_cache_include = null; + + /** + * indicate if the current code is used in a compiled + * include + * + * @var string + */ + var $_cache_including = false; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty() + { + $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] + : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']); + } + + /** + * assigns values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to assign + */ + function assign($tpl_var, $value = null) + { + if (is_array($tpl_var)){ + foreach ($tpl_var as $key => $val) { + if ($key != '') { + $this->_tpl_vars[$key] = $val; + } + } + } else { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = $value; + } + } + + /** + * assigns values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to assign + */ + function assign_by_ref($tpl_var, &$value) + { + if ($tpl_var != '') + $this->_tpl_vars[$tpl_var] = &$value; + } + + /** + * appends values to template variables + * + * @param array|string $tpl_var the template variable name(s) + * @param mixed $value the value to append + */ + function append($tpl_var, $value=null, $merge=false) + { + if (is_array($tpl_var)) { + // $tpl_var is an array, ignore $value + foreach ($tpl_var as $_key => $_val) { + if ($_key != '') { + if(!@is_array($this->_tpl_vars[$_key])) { + settype($this->_tpl_vars[$_key],'array'); + } + if($merge && is_array($_val)) { + foreach($_val as $_mkey => $_mval) { + $this->_tpl_vars[$_key][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$_key][] = $_val; + } + } + } + } else { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if($merge && is_array($value)) { + foreach($value as $_mkey => $_mval) { + $this->_tpl_vars[$tpl_var][$_mkey] = $_mval; + } + } else { + $this->_tpl_vars[$tpl_var][] = $value; + } + } + } + } + + /** + * appends values to template variables by reference + * + * @param string $tpl_var the template variable name + * @param mixed $value the referenced value to append + */ + function append_by_ref($tpl_var, &$value, $merge=false) + { + if ($tpl_var != '' && isset($value)) { + if(!@is_array($this->_tpl_vars[$tpl_var])) { + settype($this->_tpl_vars[$tpl_var],'array'); + } + if ($merge && is_array($value)) { + foreach($value as $_key => $_val) { + $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key]; + } + } else { + $this->_tpl_vars[$tpl_var][] = &$value; + } + } + } + + + /** + * clear the given assigned template variable. + * + * @param string $tpl_var the template variable to clear + */ + function clear_assign($tpl_var) + { + if (is_array($tpl_var)) + foreach ($tpl_var as $curr_var) + unset($this->_tpl_vars[$curr_var]); + else + unset($this->_tpl_vars[$tpl_var]); + } + + + /** + * Registers custom function to be used in templates + * + * @param string $function the name of the template function + * @param string $function_impl the name of the PHP function to register + */ + function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['function'][$function] = + array($function_impl, null, null, false, $cacheable, $cache_attrs); + + } + + /** + * Unregisters custom function + * + * @param string $function name of template function + */ + function unregister_function($function) + { + unset($this->_plugins['function'][$function]); + } + + /** + * Registers object to be used in templates + * + * @param string $object name of template object + * @param object &$object_impl the referenced PHP object to register + * @param null|array $allowed list of allowed methods (empty = all) + * @param boolean $smarty_args smarty argument format, else traditional + * @param null|array $block_functs list of methods that are block format + */ + function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + { + settype($allowed, 'array'); + settype($smarty_args, 'boolean'); + $this->_reg_objects[$object] = + array(&$object_impl, $allowed, $smarty_args, $block_methods); + } + + /** + * Unregisters object + * + * @param string $object name of template object + */ + function unregister_object($object) + { + unset($this->_reg_objects[$object]); + } + + + /** + * Registers block function to be used in templates + * + * @param string $block name of template block + * @param string $block_impl PHP function to register + */ + function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null) + { + $this->_plugins['block'][$block] = + array($block_impl, null, null, false, $cacheable, $cache_attrs); + } + + /** + * Unregisters block function + * + * @param string $block name of template function + */ + function unregister_block($block) + { + unset($this->_plugins['block'][$block]); + } + + /** + * Registers compiler function + * + * @param string $function name of template function + * @param string $function_impl name of PHP function to register + */ + function register_compiler_function($function, $function_impl, $cacheable=true) + { + $this->_plugins['compiler'][$function] = + array($function_impl, null, null, false, $cacheable); + } + + /** + * Unregisters compiler function + * + * @param string $function name of template function + */ + function unregister_compiler_function($function) + { + unset($this->_plugins['compiler'][$function]); + } + + /** + * Registers modifier to be used in templates + * + * @param string $modifier name of template modifier + * @param string $modifier_impl name of PHP function to register + */ + function register_modifier($modifier, $modifier_impl) + { + $this->_plugins['modifier'][$modifier] = + array($modifier_impl, null, null, false); + } + + /** + * Unregisters modifier + * + * @param string $modifier name of template modifier + */ + function unregister_modifier($modifier) + { + unset($this->_plugins['modifier'][$modifier]); + } + + /** + * Registers a resource to fetch a template + * + * @param string $type name of resource + * @param array $functions array of functions to handle resource + */ + function register_resource($type, $functions) + { + if (count($functions)==4) { + $this->_plugins['resource'][$type] = + array($functions, false); + + } elseif (count($functions)==5) { + $this->_plugins['resource'][$type] = + array(array(array(&$functions[0], $functions[1]) + ,array(&$functions[0], $functions[2]) + ,array(&$functions[0], $functions[3]) + ,array(&$functions[0], $functions[4])) + ,false); + + } else { + $this->trigger_error("malformed function-list for '$type' in register_resource"); + + } + } + + /** + * Unregisters a resource + * + * @param string $type name of resource + */ + function unregister_resource($type) + { + unset($this->_plugins['resource'][$type]); + } + + /** + * Registers a prefilter function to apply + * to a template before compiling + * + * @param string $function name of PHP function to register + */ + function register_prefilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['prefilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a prefilter function + * + * @param string $function name of PHP function + */ + function unregister_prefilter($function) + { + unset($this->_plugins['prefilter'][$function]); + } + + /** + * Registers a postfilter function to apply + * to a compiled template after compilation + * + * @param string $function name of PHP function to register + */ + function register_postfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['postfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters a postfilter function + * + * @param string $function name of PHP function + */ + function unregister_postfilter($function) + { + unset($this->_plugins['postfilter'][$function]); + } + + /** + * Registers an output filter function to apply + * to a template output + * + * @param string $function name of PHP function + */ + function register_outputfilter($function) + { + $_name = (is_array($function)) ? $function[1] : $function; + $this->_plugins['outputfilter'][$_name] + = array($function, null, null, false); + } + + /** + * Unregisters an outputfilter function + * + * @param string $function name of PHP function + */ + function unregister_outputfilter($function) + { + unset($this->_plugins['outputfilter'][$function]); + } + + /** + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + */ + function load_filter($type, $name) + { + switch ($type) { + case 'output': + $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + break; + + case 'pre': + case 'post': + if (!isset($this->_plugins[$type . 'filter'][$name])) + $this->_plugins[$type . 'filter'][$name] = false; + break; + } + } + + /** + * clear cached content for the given template and cache id + * + * @param string $tpl_file name of template file + * @param string $cache_id name of cache_id + * @param string $compile_id name of compile_id + * @param string $exp_time expiration time + * @return boolean + */ + function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + if (!isset($tpl_file)) + $compile_id = null; + + $_auto_id = $this->_get_auto_id($cache_id, $compile_id); + + if (!empty($this->cache_handler_func)) { + return call_user_func_array($this->cache_handler_func, + array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time)); + } else { + $_params = array('auto_base' => $this->cache_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $_auto_id, + 'exp_time' => $exp_time); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + } + + + /** + * clear the entire contents of cache (all templates) + * + * @param string $exp_time expire time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_all_cache($exp_time = null) + { + return $this->clear_cache(null, null, null, $exp_time); + } + + + /** + * test to see if valid cache exists for this template + * + * @param string $tpl_file name of template file + * @param string $cache_id + * @param string $compile_id + * @return string|false results of {@link _read_cache_file()} + */ + function is_cached($tpl_file, $cache_id = null, $compile_id = null) + { + if (!$this->caching) + return false; + + if (!isset($compile_id)) + $compile_id = $this->compile_id; + + $_params = array( + 'tpl_file' => $tpl_file, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + return smarty_core_read_cache_file($_params, $this); + } + + + /** + * clear all the assigned template variables. + * + */ + function clear_all_assign() + { + $this->_tpl_vars = array(); + } + + /** + * clears compiled version of specified template resource, + * or all compiled template files if one is not specified. + * This function is for advanced use only, not normally needed. + * + * @param string $tpl_file + * @param string $compile_id + * @param string $exp_time + * @return boolean results of {@link smarty_core_rm_auto()} + */ + function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) + { + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + $_params = array('auto_base' => $this->compile_dir, + 'auto_source' => $tpl_file, + 'auto_id' => $compile_id, + 'exp_time' => $exp_time, + 'extensions' => array('.inc', '.php')); + require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); + return smarty_core_rm_auto($_params, $this); + } + + /** + * Checks whether requested template exists. + * + * @param string $tpl_file + * @return boolean + */ + function template_exists($tpl_file) + { + $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false); + return $this->_fetch_resource_info($_params); + } + + /** + * Returns an array containing template variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_template_vars($name=null) + { + if(!isset($name)) { + return $this->_tpl_vars; + } elseif(isset($this->_tpl_vars[$name])) { + return $this->_tpl_vars[$name]; + } else { + // var non-existant, return valid reference + $_tmp = null; + return $_tmp; + } + } + + /** + * Returns an array containing config variables + * + * @param string $name + * @param string $type + * @return array + */ + function &get_config_vars($name=null) + { + if(!isset($name) && is_array($this->_config[0])) { + return $this->_config[0]['vars']; + } else if(isset($this->_config[0]['vars'][$name])) { + return $this->_config[0]['vars'][$name]; + } else { + // var non-existant, return valid reference + $_tmp = null; + return $_tmp; + } + } + + /** + * trigger Smarty error + * + * @param string $error_msg + * @param integer $error_type + */ + function trigger_error($error_msg, $error_type = E_USER_WARNING) + { + trigger_error("Smarty error: $error_msg", $error_type); + } + + + /** + * executes & displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + */ + function display($resource_name, $cache_id = null, $compile_id = null) + { + $this->fetch($resource_name, $cache_id, $compile_id, true); + } + + /** + * executes & returns or displays the template results + * + * @param string $resource_name + * @param string $cache_id + * @param string $compile_id + * @param boolean $display + */ + function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) + { + static $_cache_info = array(); + + $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) + ? $this->error_reporting : error_reporting() & ~E_NOTICE); + + if (!$this->debugging && $this->debugging_ctrl == 'URL') { + $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']; + if (@strstr($_query_string, $this->_smarty_debug_id)) { + if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) { + // enable debugging for this browser session + @setcookie('SMARTY_DEBUG', true); + $this->debugging = true; + } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) { + // disable debugging for this browser session + @setcookie('SMARTY_DEBUG', false); + $this->debugging = false; + } else { + // enable debugging for this page + $this->debugging = true; + } + } else { + $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']); + } + } + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $resource_name, + 'depth' => 0); + $_included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + if (!isset($compile_id)) { + $compile_id = $this->compile_id; + } + + $this->_compile_id = $compile_id; + $this->_inclusion_depth = 0; + + if ($this->caching) { + // save old cache_info, initialize cache_info + array_push($_cache_info, $this->_cache_info); + $this->_cache_info = array(); + $_params = array( + 'tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => null + ); + require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); + if (smarty_core_read_cache_file($_params, $this)) { + $_smarty_results = $_params['results']; + if (!empty($this->_cache_info['insert_tags'])) { + $_params = array('plugins' => $this->_cache_info['insert_tags']); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + } + if (!empty($this->_cache_info['cache_serials'])) { + $_params = array('results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php'); + $_smarty_results = smarty_core_process_compiled_include($_params, $this); + } + + + if ($display) { + if ($this->debugging) + { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time; + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + $_smarty_results .= smarty_core_display_debug_console($_params, $this); + } + if ($this->cache_modified_check) { + $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT'; + if (@count($this->_cache_info['insert_tags']) == 0 + && !$this->_cache_serials + && $_gmt_mtime == $_last_modified_date) { + if (php_sapi_name()=='cgi') + header('Status: 304 Not Modified'); + else + header('HTTP/1.1 304 Not Modified'); + + } else { + header('Last-Modified: '.$_gmt_mtime); + echo $_smarty_results; + } + } else { + echo $_smarty_results; + } + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return true; + } else { + error_reporting($_smarty_old_error_level); + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + return $_smarty_results; + } + } else { + $this->_cache_info['template'][$resource_name] = true; + if ($this->cache_modified_check && $display) { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT'); + } + } + } + + // load filters that are marked as autoload + if (count($this->autoload_filters)) { + foreach ($this->autoload_filters as $_filter_type => $_filters) { + foreach ($_filters as $_filter) { + $this->load_filter($_filter_type, $_filter); + } + } + } + + $_smarty_compile_path = $this->_get_compile_path($resource_name); + + // if we just need to display the results, don't perform output + // buffering - for speed + $_cache_including = $this->_cache_including; + $this->_cache_including = false; + if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) { + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + } else { + ob_start(); + if ($this->_is_compiled($resource_name, $_smarty_compile_path) + || $this->_compile_resource($resource_name, $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + $_smarty_results = ob_get_contents(); + ob_end_clean(); + + foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) { + $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this)); + } + } + + if ($this->caching) { + $_params = array('tpl_file' => $resource_name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'results' => $_smarty_results); + require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php'); + smarty_core_write_cache_file($_params, $this); + require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); + $_smarty_results = smarty_core_process_cached_inserts($_params, $this); + + if ($this->_cache_serials) { + // strip nocache-tags from output + $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s' + ,'' + ,$_smarty_results); + } + // restore initial cache_info + $this->_cache_info = array_pop($_cache_info); + } + $this->_cache_including = $_cache_including; + + if ($display) { + if (isset($_smarty_results)) { echo $_smarty_results; } + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time); + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + echo smarty_core_display_debug_console($_params, $this); + } + error_reporting($_smarty_old_error_level); + return; + } else { + error_reporting($_smarty_old_error_level); + if (isset($_smarty_results)) { return $_smarty_results; } + } + } + + /** + * load configuration values + * + * @param string $file + * @param string $section + * @param string $scope + */ + function config_load($file, $section = null, $scope = 'global') + { + require_once($this->_get_plugin_filepath('function', 'config_load')); + smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this); + } + + /** + * return a reference to a registered object + * + * @param string $name + * @return object + */ + function &get_registered_object($name) { + if (!isset($this->_reg_objects[$name])) + $this->_trigger_fatal_error("'$name' is not a registered object"); + + if (!is_object($this->_reg_objects[$name][0])) + $this->_trigger_fatal_error("registered '$name' is not an object"); + + return $this->_reg_objects[$name][0]; + } + + /** + * clear configuration values + * + * @param string $var + */ + function clear_config($var = null) + { + if(!isset($var)) { + // clear all values + $this->_config = array(array('vars' => array(), + 'files' => array())); + } else { + unset($this->_config[0]['vars'][$var]); + } + } + + /** + * get filepath of requested plugin + * + * @param string $type + * @param string $name + * @return string|false + */ + function _get_plugin_filepath($type, $name) + { + $_params = array('type' => $type, 'name' => $name); + require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php'); + return smarty_core_assemble_plugin_filepath($_params, $this); + } + + /** + * test if resource needs compiling + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _is_compiled($resource_name, $compile_path) + { + if (!$this->force_compile && file_exists($compile_path)) { + if (!$this->compile_check) { + // no need to check compiled file + return true; + } else { + // get file source and timestamp + $_params = array('resource_name' => $resource_name, 'get_source'=>false); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + if ($_params['resource_timestamp'] <= filemtime($compile_path)) { + // template not expired, no recompile + return true; + } else { + // compile template + return false; + } + } + } else { + // compiled template does not exist, or forced compile + return false; + } + } + + /** + * compile the template + * + * @param string $resource_name + * @param string $compile_path + * @return boolean + */ + function _compile_resource($resource_name, $compile_path) + { + + $_params = array('resource_name' => $resource_name); + if (!$this->_fetch_resource_info($_params)) { + return false; + } + + $_source_content = $_params['source_content']; + $_cache_include = substr($compile_path, 0, -4).'.inc'; + + if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) { + // if a _cache_serial was set, we also have to write an include-file: + if ($this->_cache_include_info) { + require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php'); + smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)), $this); + } + + $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $this); + + return true; + } else { + return false; + } + + } + + /** + * compile the given source + * + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return boolean + */ + function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null) + { + if (file_exists(SMARTY_DIR . $this->compiler_file)) { + require_once(SMARTY_DIR . $this->compiler_file); + } else { + // use include_path + require_once($this->compiler_file); + } + + + $smarty_compiler = new $this->compiler_class; + + $smarty_compiler->template_dir = $this->template_dir; + $smarty_compiler->compile_dir = $this->compile_dir; + $smarty_compiler->plugins_dir = $this->plugins_dir; + $smarty_compiler->config_dir = $this->config_dir; + $smarty_compiler->force_compile = $this->force_compile; + $smarty_compiler->caching = $this->caching; + $smarty_compiler->php_handling = $this->php_handling; + $smarty_compiler->left_delimiter = $this->left_delimiter; + $smarty_compiler->right_delimiter = $this->right_delimiter; + $smarty_compiler->_version = $this->_version; + $smarty_compiler->security = $this->security; + $smarty_compiler->secure_dir = $this->secure_dir; + $smarty_compiler->security_settings = $this->security_settings; + $smarty_compiler->trusted_dir = $this->trusted_dir; + $smarty_compiler->use_sub_dirs = $this->use_sub_dirs; + $smarty_compiler->_reg_objects = &$this->_reg_objects; + $smarty_compiler->_plugins = &$this->_plugins; + $smarty_compiler->_tpl_vars = &$this->_tpl_vars; + $smarty_compiler->default_modifiers = $this->default_modifiers; + $smarty_compiler->compile_id = $this->_compile_id; + $smarty_compiler->_config = $this->_config; + $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals; + + if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) { + $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path]; + } + $smarty_compiler->_cache_include = $cache_include_path; + + + $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content); + + if ($smarty_compiler->_cache_serial) { + $this->_cache_include_info = array( + 'cache_serial'=>$smarty_compiler->_cache_serial + ,'plugins_code'=>$smarty_compiler->_plugins_code + ,'include_file_path' => $cache_include_path); + + } else { + $this->_cache_include_info = null; + + } + + return $_results; + } + + /** + * Get the compile path for this resource + * + * @param string $resource_name + * @return string results of {@link _get_auto_filename()} + */ + function _get_compile_path($resource_name) + { + return $this->_get_auto_filename($this->compile_dir, $resource_name, + $this->_compile_id) . '.php'; + } + + /** + * fetch the template info. Gets timestamp, and source + * if get_source is true + * + * sets $source_content to the source of the template, and + * $resource_timestamp to its time stamp + * @param string $resource_name + * @param string $source_content + * @param integer $resource_timestamp + * @param boolean $get_source + * @param boolean $quiet + * @return boolean + */ + + function _fetch_resource_info(&$params) + { + if(!isset($params['get_source'])) { $params['get_source'] = true; } + if(!isset($params['quiet'])) { $params['quiet'] = false; } + + $_return = false; + $_params = array('resource_name' => $params['resource_name']) ; + if (isset($params['resource_base_path'])) + $_params['resource_base_path'] = $params['resource_base_path']; + else + $_params['resource_base_path'] = $this->template_dir; + + if ($this->_parse_resource_name($_params)) { + $_resource_type = $_params['resource_type']; + $_resource_name = $_params['resource_name']; + switch ($_resource_type) { + case 'file': + if ($params['get_source']) { + $params['source_content'] = $this->_read_file($_resource_name); + } + $params['resource_timestamp'] = filemtime($_resource_name); + $_return = is_file($_resource_name); + break; + + default: + // call resource functions to fetch the template source and timestamp + if ($params['get_source']) { + $_source_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][0], + array($_resource_name, &$params['source_content'], &$this)); + } else { + $_source_return = true; + } + + $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) && + call_user_func_array($this->_plugins['resource'][$_resource_type][0][1], + array($_resource_name, &$params['resource_timestamp'], &$this)); + + $_return = $_source_return && $_timestamp_return; + break; + } + } + + if (!$_return) { + // see if we can get a template with the default template handler + if (!empty($this->default_template_handler_func)) { + if (!is_callable($this->default_template_handler_func)) { + $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist."); + } else { + $_return = call_user_func_array( + $this->default_template_handler_func, + array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this)); + } + } + } + + if (!$_return) { + if (!$params['quiet']) { + $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"'); + } + } else if ($_return && $this->security) { + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if (!smarty_core_is_secure($_params, $this)) { + if (!$params['quiet']) + $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed'); + $params['source_content'] = null; + $params['resource_timestamp'] = null; + return false; + } + } + return $_return; + } + + + /** + * parse out the type and name from the resource + * + * @param string $resource_base_path + * @param string $resource_name + * @param string $resource_type + * @param string $resource_name + * @return boolean + */ + + function _parse_resource_name(&$params) + { + + // split tpl_path by the first colon + $_resource_name_parts = explode(':', $params['resource_name'], 2); + + if (count($_resource_name_parts) == 1) { + // no resource type given + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $_resource_name_parts[0]; + } else { + if(strlen($_resource_name_parts[0]) == 1) { + // 1 char is not resource type, but part of filepath + $params['resource_type'] = $this->default_resource_type; + $params['resource_name'] = $params['resource_name']; + } else { + $params['resource_type'] = $_resource_name_parts[0]; + $params['resource_name'] = $_resource_name_parts[1]; + } + } + + if ($params['resource_type'] == 'file') { + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) { + // relative pathname to $params['resource_base_path'] + // use the first directory where the file is found + foreach ((array)$params['resource_base_path'] as $_curr_path) { + $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name']; + if (file_exists($_fullpath) && is_file($_fullpath)) { + $params['resource_name'] = $_fullpath; + return true; + } + // didn't find the file, try include_path + $_params = array('file_path' => $_fullpath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $this)) { + $params['resource_name'] = $_params['new_file_path']; + return true; + } + } + return false; + } else { + /* absolute path */ + return file_exists($params['resource_name']); + } + } elseif (empty($this->_plugins['resource'][$params['resource_type']])) { + $_params = array('type' => $params['resource_type']); + require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php'); + smarty_core_load_resource_plugin($_params, $this); + } + + return true; + } + + + /** + * Handle modifiers + * + * @param string|null $modifier_name + * @param array|null $map_array + * @return string result of modifiers + */ + function _run_mod_handler() + { + $_args = func_get_args(); + list($_modifier_name, $_map_array) = array_splice($_args, 0, 2); + list($_func_name, $_tpl_file, $_tpl_line) = + $this->_plugins['modifier'][$_modifier_name]; + + $_var = $_args[0]; + foreach ($_var as $_key => $_val) { + $_args[0] = $_val; + $_var[$_key] = call_user_func_array($_func_name, $_args); + } + return $_var; + } + + /** + * Remove starting and ending quotes from the string + * + * @param string $string + * @return string + */ + function _dequote($string) + { + if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') && + substr($string, -1) == substr($string, 0, 1)) + return substr($string, 1, -1); + else + return $string; + } + + + /** + * read in a file + * + * @param string $filename + * @return string + */ + function _read_file($filename) + { + if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) { + $contents = ''; + while (!feof($fd)) { + $contents .= fread($fd, 8192); + } + fclose($fd); + return $contents; + } else { + return false; + } + } + + /** + * get a concrete filename for automagically created content + * + * @param string $auto_base + * @param string $auto_source + * @param string $auto_id + * @return string + * @staticvar string|null + * @staticvar string|null + */ + function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null) + { + $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + $_return = $auto_base . DIRECTORY_SEPARATOR; + + if(isset($auto_id)) { + // make auto_id safe for directory names + $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id))); + // split into separate directories + $_return .= $auto_id . $_compile_dir_sep; + } + + if(isset($auto_source)) { + // make source name safe for filename + $_filename = urlencode(basename($auto_source)); + $_crc32 = sprintf('%08X', crc32($auto_source)); + // prepend %% to avoid name conflicts with + // with $params['auto_id'] names + $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep . + substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32; + $_return .= '%%' . $_crc32 . '%%' . $_filename; + } + + return $_return; + } + + /** + * unlink a file, possibly using expiration time + * + * @param string $resource + * @param integer $exp_time + */ + function _unlink($resource, $exp_time = null) + { + if(isset($exp_time)) { + if(time() - @filemtime($resource) >= $exp_time) { + return @unlink($resource); + } + } else { + return @unlink($resource); + } + } + + /** + * returns an auto_id for auto-file-functions + * + * @param string $cache_id + * @param string $compile_id + * @return string|null + */ + function _get_auto_id($cache_id=null, $compile_id=null) { + if (isset($cache_id)) + return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id; + elseif(isset($compile_id)) + return $compile_id; + else + return null; + } + + /** + * trigger Smarty plugin error + * + * @param string $error_msg + * @param string $tpl_file + * @param integer $tpl_line + * @param string $file + * @param integer $line + * @param integer $error_type + */ + function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null, + $file = null, $line = null, $error_type = E_USER_ERROR) + { + if(isset($file) && isset($line)) { + $info = ' ('.basename($file).", line $line)"; + } else { + $info = ''; + } + if (isset($tpl_line) && isset($tpl_file)) { + $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type); + } else { + $this->trigger_error($error_msg . $info, $error_type); + } + } + + + /** + * callback function for preg_replace, to call a non-cacheable block + * @return string + */ + function _process_compiled_include_callback($match) { + $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3]; + ob_start(); + $_func($this); + $_ret = ob_get_contents(); + ob_end_clean(); + return $_ret; + } + + + /** + * called for included templates + * + * @param string $_smarty_include_tpl_file + * @param string $_smarty_include_vars + */ + + // $_smarty_include_tpl_file, $_smarty_include_vars + + function _smarty_include($params) + { + if ($this->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $this); + $this->_smarty_debug_info[] = array('type' => 'template', + 'filename' => $params['smarty_include_tpl_file'], + 'depth' => ++$this->_inclusion_depth); + $included_tpls_idx = count($this->_smarty_debug_info) - 1; + } + + $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']); + + // config vars are treated as local, so push a copy of the + // current ones onto the front of the stack + array_unshift($this->_config, $this->_config[0]); + + $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']); + + + if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path) + || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path)) + { + include($_smarty_compile_path); + } + + // pop the local vars off the front of the stack + array_shift($this->_config); + + $this->_inclusion_depth--; + + if ($this->debugging) { + // capture time for debugging info + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time; + } + + if ($this->caching) { + $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true; + } + } + + + /** + * get or set an array of cached attributes for function that is + * not cacheable + * @return array + */ + function &_smarty_cache_attrs($cache_serial, $count) { + $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count]; + + if ($this->_cache_including) { + /* return next set of cache_attrs */ + $_return = current($_cache_attrs); + next($_cache_attrs); + return $_return; + + } else { + /* add a reference to a new set of cache_attrs */ + $_cache_attrs[] = array(); + return $_cache_attrs[count($_cache_attrs)-1]; + + } + + } + + + /** + * wrapper for include() retaining $this + * @return mixed + */ + function _include($filename, $once=false, $params=null) + { + if ($once) { + return include_once($filename); + } else { + return include($filename); + } + } + + + /** + * wrapper for eval() retaining $this + * @return mixed + */ + function _eval($code, $params=null) + { + return eval($code); + } + /**#@-*/ + +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/Smarty_Compiler.class.php b/Tools/projectGenerator/smarty/Smarty_Compiler.class.php new file mode 100644 index 000000000..4835a9699 --- /dev/null +++ b/Tools/projectGenerator/smarty/Smarty_Compiler.class.php @@ -0,0 +1,2328 @@ + + * @author Andrei Zmievski + * @version 2.6.18 + * @copyright 2001-2005 New Digital Group, Inc. + * @package Smarty + */ + +/* $Id: Smarty_Compiler.class.php,v 1.395 2007/03/06 10:40:06 messju Exp $ */ + +/** + * Template compiling class + * @package Smarty + */ +class Smarty_Compiler extends Smarty { + + // internal vars + /**#@+ + * @access private + */ + var $_folded_blocks = array(); // keeps folded template blocks + var $_current_file = null; // the current template being compiled + var $_current_line_no = 1; // line number for error messages + var $_capture_stack = array(); // keeps track of nested capture buffers + var $_plugin_info = array(); // keeps track of plugins to load + var $_init_smarty_vars = false; + var $_permitted_tokens = array('true','false','yes','no','on','off','null'); + var $_db_qstr_regexp = null; // regexps are setup in the constructor + var $_si_qstr_regexp = null; + var $_qstr_regexp = null; + var $_func_regexp = null; + var $_reg_obj_regexp = null; + var $_var_bracket_regexp = null; + var $_num_const_regexp = null; + var $_dvar_guts_regexp = null; + var $_dvar_regexp = null; + var $_cvar_regexp = null; + var $_svar_regexp = null; + var $_avar_regexp = null; + var $_mod_regexp = null; + var $_var_regexp = null; + var $_parenth_param_regexp = null; + var $_func_call_regexp = null; + var $_obj_ext_regexp = null; + var $_obj_start_regexp = null; + var $_obj_params_regexp = null; + var $_obj_call_regexp = null; + var $_cacheable_state = 0; + var $_cache_attrs_count = 0; + var $_nocache_count = 0; + var $_cache_serial = null; + var $_cache_include = null; + + var $_strip_depth = 0; + var $_additional_newline = "\n"; + + /**#@-*/ + /** + * The class constructor. + */ + function Smarty_Compiler() + { + // matches double quoted strings: + // "foobar" + // "foo\"bar" + $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"'; + + // matches single quoted strings: + // 'foobar' + // 'foo\'bar' + $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\''; + + // matches single or double quoted strings + $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')'; + + // matches bracket portion of vars + // [0] + // [foo] + // [$bar] + $this->_var_bracket_regexp = '\[\$?[\w\.]+\]'; + + // matches numerical constants + // 30 + // -12 + // 13.22 + $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)'; + + // matches $ vars (not objects): + // $foo + // $foo.bar + // $foo.bar.foobar + // $foo[0] + // $foo[$bar] + // $foo[5][blah] + // $foo[5].bar[$foobar][4] + $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))'; + $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]'; + $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp + . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?'; + $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp; + + // matches config vars: + // #foo# + // #foobar123_foo# + $this->_cvar_regexp = '\#\w+\#'; + + // matches section vars: + // %foo.bar% + $this->_svar_regexp = '\%\w+\.\w+\%'; + + // matches all valid variables (no quotes, no modifiers) + $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|' + . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')'; + + // matches valid variable syntax: + // $foo + // $foo + // #foo# + // #foo# + // "text" + // "text" + $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')'; + + // matches valid object call (one level of object nesting allowed in parameters): + // $foo->bar + // $foo->bar() + // $foo->bar("text") + // $foo->bar($foo, $bar, "text") + // $foo->bar($foo, "foo") + // $foo->bar->foo() + // $foo->bar->foo->bar() + // $foo->bar($foo->bar) + // $foo->bar($foo->bar()) + // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar)) + $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')'; + $this->_obj_restricted_param_regexp = '(?:' + . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')' + . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)'; + $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)'; + $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp + . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)'; + $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)'; + $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)'; + + // matches valid modifier syntax: + // |foo + // |@foo + // |foo:"bar" + // |foo:$bar + // |foo:"bar":$foobar + // |foo|bar + // |foo:$foo->bar + $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|' + . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)'; + + // matches valid function name: + // foo123 + // _foo_bar + $this->_func_regexp = '[a-zA-Z_]\w*'; + + // matches valid registered object: + // foo->bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*'; + + // matches valid parameter values: + // true + // $foo + // $foo|bar + // #foo# + // #foo#|bar + // "text" + // "text"|bar + // $foo->bar + $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|' + . $this->_var_regexp . '|' . $this->_num_const_regexp . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)'; + + // matches valid parenthesised function parameters: + // + // "text" + // $foo, $bar, "text" + // $foo|bar, "foo"|bar, $foo->bar($foo)|bar + $this->_parenth_param_regexp = '(?:\((?:\w+|' + . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|' + . $this->_param_regexp . ')))*)?\))'; + + // matches valid function call: + // foo() + // foo_bar($foo) + // _foo_bar($foo,"bar") + // foo123($foo,$foo->bar(),"foo") + $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:' + . $this->_parenth_param_regexp . '))'; + } + + /** + * compile a resource + * + * sets $compiled_content to the compiled source + * @param string $resource_name + * @param string $source_content + * @param string $compiled_content + * @return true + */ + function _compile_file($resource_name, $source_content, &$compiled_content) + { + + if ($this->security) { + // do not allow php syntax to be executed unless specified + if ($this->php_handling == SMARTY_PHP_ALLOW && + !$this->security_settings['PHP_HANDLING']) { + $this->php_handling = SMARTY_PHP_PASSTHRU; + } + } + + $this->_load_filters(); + + $this->_current_file = $resource_name; + $this->_current_line_no = 1; + $ldq = preg_quote($this->left_delimiter, '~'); + $rdq = preg_quote($this->right_delimiter, '~'); + + // run template source through prefilter functions + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) continue; + if ($prefilter[3] || is_callable($prefilter[0])) { + $source_content = call_user_func_array($prefilter[0], + array($source_content, &$this)); + $this->_plugins['prefilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented"); + } + } + } + + /* fetch all special blocks */ + $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s"; + + preg_match_all($search, $source_content, $match, PREG_SET_ORDER); + $this->_folded_blocks = $match; + reset($this->_folded_blocks); + + /* replace special blocks by "{php}" */ + $source_content = preg_replace($search.'e', "'" + . $this->_quote_replace($this->left_delimiter) . 'php' + . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'" + . $this->_quote_replace($this->right_delimiter) + . "'" + , $source_content); + + /* Gather all template tags. */ + preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match); + $template_tags = $_match[1]; + /* Split content by template tags to obtain non-template content. */ + $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content); + + /* loop through text blocks */ + for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) { + /* match anything resembling php tags */ + if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?\s*php\s*[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) { + /* replace tags with placeholders to prevent recursive replacements */ + $sp_match[1] = array_unique($sp_match[1]); + usort($sp_match[1], '_smarty_sort_length'); + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]); + } + /* process each one */ + for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) { + if ($this->php_handling == SMARTY_PHP_PASSTHRU) { + /* echo php contents */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', ''."\n", $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_QUOTE) { + /* quote php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]); + } else if ($this->php_handling == SMARTY_PHP_REMOVE) { + /* remove php tags */ + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]); + } else { + /* SMARTY_PHP_ALLOW, but echo non php starting tags */ + $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', ''."\n", $sp_match[1][$curr_sp]); + $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]); + } + } + } + } + + /* Compile the template tags into PHP code. */ + $compiled_tags = array(); + for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) { + $this->_current_line_no += substr_count($text_blocks[$i], "\n"); + $compiled_tags[] = $this->_compile_tag($template_tags[$i]); + $this->_current_line_no += substr_count($template_tags[$i], "\n"); + } + if (count($this->_tag_stack)>0) { + list($_open_tag, $_line_no) = end($this->_tag_stack); + $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__); + return; + } + + /* Reformat $text_blocks between 'strip' and '/strip' tags, + removing spaces, tabs and newlines. */ + $strip = false; + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '{strip}') { + $compiled_tags[$i] = ''; + $strip = true; + /* remove leading whitespaces */ + $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]); + } + if ($strip) { + /* strip all $text_blocks before the next '/strip' */ + for ($j = $i + 1; $j < $for_max; $j++) { + /* remove leading and trailing whitespaces of each line */ + $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]); + if ($compiled_tags[$j] == '{/strip}') { + /* remove trailing whitespaces from the last text_block */ + $text_blocks[$j] = rtrim($text_blocks[$j]); + } + $text_blocks[$j] = ""\'", "\\"=>"\\\\")) . "'; ?>"; + if ($compiled_tags[$j] == '{/strip}') { + $compiled_tags[$j] = "\n"; /* slurped by php, but necessary + if a newline is following the closing strip-tag */ + $strip = false; + $i = $j; + break; + } + } + } + } + $compiled_content = ''; + + $tag_guard = '%%%SMARTYOTG' . md5(uniqid(rand(), true)) . '%%%'; + + /* Interleave the compiled contents and text blocks to get the final result. */ + for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) { + if ($compiled_tags[$i] == '') { + // tag result empty, remove first newline from following text block + $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]); + } + // replace legit PHP tags with placeholder + $text_blocks[$i] = str_replace('\n", $compiled_content); + $compiled_content = preg_replace("~(?\n", $compiled_content); + + // recover legit tags + $compiled_content = str_replace($tag_guard, '_cache_serial)) { + $compiled_content = "_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content; + } + + // run compiled template through postfilter functions + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) continue; + if ($postfilter[3] || is_callable($postfilter[0])) { + $compiled_content = call_user_func_array($postfilter[0], + array($compiled_content, &$this)); + $this->_plugins['postfilter'][$filter_name][3] = true; + } else { + $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented"); + } + } + } + + // put header at the top of the compiled template + date_default_timezone_set('America/Los_Angeles'); + $template_header = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $template_header .= " compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n"; + + /* Emit code to load needed plugins. */ + $this->_plugins_code = ''; + if (count($this->_plugin_info)) { + $_plugins_params = "array('plugins' => array("; + foreach ($this->_plugin_info as $plugin_type => $plugins) { + foreach ($plugins as $plugin_name => $plugin_info) { + $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], "; + $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),'; + } + } + $_plugins_params .= '))'; + $plugins_code = "\n"; + $template_header .= $plugins_code; + $this->_plugin_info = array(); + $this->_plugins_code = $plugins_code; + } + + if ($this->_init_smarty_vars) { + $template_header .= "\n"; + $this->_init_smarty_vars = false; + } + + $compiled_content = $template_header . $compiled_content; + return true; + } + + /** + * Compile a template tag + * + * @param string $template_tag + * @return string + */ + function _compile_tag($template_tag) + { + /* Matched comment. */ + if (substr($template_tag, 0, 1) == '*' && substr($template_tag, -1) == '*') + return ''; + + /* Split tag into two three parts: command, command modifiers and the arguments. */ + if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + (?:\s+(.*))?$ + ~xs', $template_tag, $match)) { + $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $tag_command = $match[1]; + $tag_modifier = isset($match[2]) ? $match[2] : null; + $tag_args = isset($match[3]) ? $match[3] : null; + + if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) { + /* tag name is a variable or object */ + $_return = $this->_parse_var_props($tag_command . $tag_modifier); + return "" . $this->_additional_newline; + } + + /* If the tag name is a registered object, we process it. */ + if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) { + return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier); + } + + switch ($tag_command) { + case 'include': + return $this->_compile_include_tag($tag_args); + + case 'include_php': + return $this->_compile_include_php_tag($tag_args); + + case 'if': + $this->_push_tag('if'); + return $this->_compile_if_tag($tag_args); + + case 'else': + list($_open_tag) = end($this->_tag_stack); + if ($_open_tag != 'if' && $_open_tag != 'elseif') + $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__); + else + $this->_push_tag('else'); + return ''; + + case 'elseif': + list($_open_tag) = end($this->_tag_stack); + if ($_open_tag != 'if' && $_open_tag != 'elseif') + $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__); + if ($_open_tag == 'if') + $this->_push_tag('elseif'); + return $this->_compile_if_tag($tag_args, true); + + case '/if': + $this->_pop_tag('if'); + return ''; + + case 'capture': + return $this->_compile_capture_tag(true, $tag_args); + + case '/capture': + return $this->_compile_capture_tag(false); + + case 'ldelim': + return $this->left_delimiter; + + case 'rdelim': + return $this->right_delimiter; + + case 'section': + $this->_push_tag('section'); + return $this->_compile_section_start($tag_args); + + case 'sectionelse': + $this->_push_tag('sectionelse'); + return ""; + break; + + case '/section': + $_open_tag = $this->_pop_tag('section'); + if ($_open_tag == 'sectionelse') + return ""; + else + return ""; + + case 'foreach': + $this->_push_tag('foreach'); + return $this->_compile_foreach_start($tag_args); + break; + + case 'foreachelse': + $this->_push_tag('foreachelse'); + return ""; + + case '/foreach': + $_open_tag = $this->_pop_tag('foreach'); + if ($_open_tag == 'foreachelse') + return ""; + else + return ""; + break; + + case 'strip': + case '/strip': + if (substr($tag_command, 0, 1)=='/') { + $this->_pop_tag('strip'); + if (--$this->_strip_depth==0) { /* outermost closing {/strip} */ + $this->_additional_newline = "\n"; + return '{' . $tag_command . '}'; + } + } else { + $this->_push_tag('strip'); + if ($this->_strip_depth++==0) { /* outermost opening {strip} */ + $this->_additional_newline = ""; + return '{' . $tag_command . '}'; + } + } + return ''; + + case 'php': + /* handle folded tags replaced by {php} */ + list(, $block) = each($this->_folded_blocks); + $this->_current_line_no += substr_count($block[0], "\n"); + /* the number of matched elements in the regexp in _compile_file() + determins the type of folded tag that was found */ + switch (count($block)) { + case 2: /* comment */ + return ''; + + case 3: /* literal */ + return ""\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline; + + case 4: /* php */ + if ($this->security && !$this->security_settings['PHP_TAGS']) { + $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__); + return; + } + return ''; + } + break; + + case 'insert': + return $this->_compile_insert_tag($tag_args); + + default: + if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) { + return $output; + } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) { + return $output; + } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) { + return $output; + } else { + $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__); + } + + } + } + + + /** + * compile the custom compiler tag + * + * sets $output to the compiled custom compiler tag + * @param string $tag_command + * @param string $tag_args + * @param string $output + * @return boolean + */ + function _compile_compiler_tag($tag_command, $tag_args, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the compiler function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['compiler'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['compiler'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "compiler function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_compiler_' . $tag_command; + if (!is_callable($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true); + } + } + + /* + * True return value means that we either found a plugin or a + * dynamically registered function. False means that we didn't and the + * compiler should now emit code to load custom function plugin for this + * tag. + */ + if ($found) { + if ($have_function) { + $output = call_user_func_array($plugin_func, array($tag_args, &$this)); + if($output != '') { + $output = '_push_cacheable_state('compiler', $tag_command) + . $output + . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>'; + } + } else { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + } + return true; + } else { + return false; + } + } + + + /** + * compile block function tag + * + * sets $output to compiled block function tag + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @param string $output + * @return boolean + */ + function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + if (substr($tag_command, 0, 1) == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else + $start_tag = true; + + $found = false; + $have_function = true; + + /* + * First we check if the block function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['block'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['block'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "block function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_block_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* + * Even though we've located the plugin function, compilation + * happens only once, so the plugin will still need to be loaded + * at runtime for future requests. + */ + $this->_add_plugin('block', $tag_command); + + if ($start_tag) + $this->_push_tag($tag_command); + else + $this->_pop_tag($tag_command); + + if ($start_tag) { + $output = '_push_cacheable_state('block', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $_cache_attrs=''; + $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs); + $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); '; + $output .= '$_block_repeat=true;' . $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat);'; + $output .= 'while ($_block_repeat) { ob_start(); ?>'; + } else { + $output = '_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat)'; + if ($tag_modifier != '') { + $this->_parse_modifiers($_out_tag_text, $tag_modifier); + } + $output .= '$_block_repeat=false;echo ' . $_out_tag_text . '; } '; + $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>'; + } + + return true; + } + + + /** + * compile custom function tag + * + * @param string $tag_command + * @param string $tag_args + * @param string $tag_modifier + * @return string + */ + function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output) + { + $found = false; + $have_function = true; + + /* + * First we check if the custom function has already been registered + * or loaded from a plugin file. + */ + if (isset($this->_plugins['function'][$tag_command])) { + $found = true; + $plugin_func = $this->_plugins['function'][$tag_command][0]; + if (!is_callable($plugin_func)) { + $message = "custom function '$tag_command' is not implemented"; + $have_function = false; + } + } + /* + * Otherwise we need to load plugin file and look for the function + * inside it. + */ + else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) { + $found = true; + + include_once $plugin_file; + + $plugin_func = 'smarty_function_' . $tag_command; + if (!function_exists($plugin_func)) { + $message = "plugin function $plugin_func() not found in $plugin_file\n"; + $have_function = false; + } else { + $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true); + + } + } + + if (!$found) { + return false; + } else if (!$have_function) { + $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__); + return true; + } + + /* declare plugin to be loaded on display of the template that + we compile right now */ + $this->_add_plugin('function', $tag_command); + + $_cacheable_state = $this->_push_cacheable_state('function', $tag_command); + $attrs = $this->_parse_attrs($tag_args); + $_cache_attrs = ''; + $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs); + + $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)"; + if($tag_modifier != '') { + $this->_parse_modifiers($output, $tag_modifier); + } + + if($output != '') { + $output = '_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline; + } + + return true; + } + + /** + * compile a registered object tag + * + * @param string $tag_command + * @param array $attrs + * @param string $tag_modifier + * @return string + */ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + if (substr($tag_command, 0, 1) == '/') { + $start_tag = false; + $tag_command = substr($tag_command, 1); + } else { + $start_tag = true; + } + + list($object, $obj_comp) = explode('->', $tag_command); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + unset($attrs['assign']); + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if($this->_reg_objects[$object][2]) { + // smarty object argument format + $args = "array(".implode(',', (array)$arg_list)."), \$this"; + } else { + // traditional argument format + $args = implode(',', array_values($attrs)); + if (empty($args)) { + $args = 'null'; + } + } + + $prefix = ''; + $postfix = ''; + $newline = ''; + if(!is_object($this->_reg_objects[$object][0])) { + $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) { + $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) { + // method + if(in_array($obj_comp, $this->_reg_objects[$object][3])) { + // block method + if ($start_tag) { + $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); "; + $prefix .= "\$_block_repeat=true; \$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat); "; + $prefix .= "while (\$_block_repeat) { ob_start();"; + $return = null; + $postfix = ''; + } else { + $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); \$_block_repeat=false;"; + $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat)"; + $postfix = "} array_pop(\$this->_tag_stack);"; + } + } else { + // non-block method + $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)"; + } + } else { + // property + $return = "\$this->_reg_objects['$object'][0]->$obj_comp"; + } + + if($return != null) { + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if(!empty($_assign_var)) { + $output = "\$this->assign('" . $this->_dequote($_assign_var) ."', $return);"; + } else { + $output = 'echo ' . $return . ';'; + $newline = $this->_additional_newline; + } + } else { + $output = ''; + } + + return '" . $newline; + } + + /** + * Compile {insert ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_insert_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $name = $this->_dequote($attrs['name']); + + if (empty($name)) { + return $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!preg_match('~^\w+$~', $name)) { + return $this->_syntax_error("'insert: 'name' must be an insert function name", E_USER_ERROR, __FILE__, __LINE__); + } + + if (!empty($attrs['script'])) { + $delayed_loading = true; + } else { + $delayed_loading = false; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $this->_add_plugin('insert', $name, $delayed_loading); + + $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))"; + + return "" . $this->_additional_newline; + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__); + } + + foreach ($attrs as $arg_name => $arg_value) { + if ($arg_name == 'file') { + $include_file = $arg_value; + continue; + } else if ($arg_name == 'assign') { + $assign_var = $arg_value; + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $output = '_tpl_vars;\n"; + + + $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))"; + $output .= "\$this->_smarty_include($_params);\n" . + "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" . + "unset(\$_smarty_tpl_vars);\n"; + + if (isset($assign_var)) { + $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n"; + } + + $output .= ' ?>'; + + return $output; + + } + + /** + * Compile {include ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_include_php_tag($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + + if (empty($attrs['file'])) { + $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__); + } + + $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']); + $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true'; + + $arg_list = array(); + foreach($attrs as $arg_name => $arg_value) { + if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') { + if(is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))"; + + return "" . $this->_additional_newline; + } + + + /** + * Compile {section ...} tag + * + * @param string $tag_args + * @return string + */ + function _compile_section_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + $output = '_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__); + } + + $output .= "unset(\$this->_sections[$section_name]);\n"; + $section_props = "\$this->_sections[$section_name]"; + + foreach ($attrs as $attr_name => $attr_value) { + switch ($attr_name) { + case 'loop': + $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n"; + break; + + case 'show': + if (is_bool($attr_value)) + $show_attr_value = $attr_value ? 'true' : 'false'; + else + $show_attr_value = "(bool)$attr_value"; + $output .= "{$section_props}['show'] = $show_attr_value;\n"; + break; + + case 'name': + $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + break; + + case 'max': + case 'start': + $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; + break; + + case 'step': + $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n"; + break; + + default: + $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + } + + if (!isset($attrs['show'])) + $output .= "{$section_props}['show'] = true;\n"; + + if (!isset($attrs['loop'])) + $output .= "{$section_props}['loop'] = 1;\n"; + + if (!isset($attrs['max'])) + $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; + else + $output .= "if ({$section_props}['max'] < 0)\n" . + " {$section_props}['max'] = {$section_props}['loop'];\n"; + + if (!isset($attrs['step'])) + $output .= "{$section_props}['step'] = 1;\n"; + + if (!isset($attrs['start'])) + $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n"; + else { + $output .= "if ({$section_props}['start'] < 0)\n" . + " {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" . + "else\n" . + " {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n"; + } + + $output .= "if ({$section_props}['show']) {\n"; + if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) { + $output .= " {$section_props}['total'] = {$section_props}['loop'];\n"; + } else { + $output .= " {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n"; + } + $output .= " if ({$section_props}['total'] == 0)\n" . + " {$section_props}['show'] = false;\n" . + "} else\n" . + " {$section_props}['total'] = 0;\n"; + + $output .= "if ({$section_props}['show']):\n"; + $output .= " + for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; + {$section_props}['iteration'] <= {$section_props}['total']; + {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n"; + $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n"; + $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n"; + $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n"; + $output .= "{$section_props}['first'] = ({$section_props}['iteration'] == 1);\n"; + $output .= "{$section_props}['last'] = ({$section_props}['iteration'] == {$section_props}['total']);\n"; + + $output .= "?>"; + + return $output; + } + + + /** + * Compile {foreach ...} tag. + * + * @param string $tag_args + * @return string + */ + function _compile_foreach_start($tag_args) + { + $attrs = $this->_parse_attrs($tag_args); + $arg_list = array(); + + if (empty($attrs['from'])) { + return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + $from = $attrs['from']; + + if (empty($attrs['item'])) { + return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__); + } + $item = $this->_dequote($attrs['item']); + if (!preg_match('~^\w+$~', $item)) { + return $this->_syntax_error("'foreach: 'item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__); + } + + if (isset($attrs['key'])) { + $key = $this->_dequote($attrs['key']); + if (!preg_match('~^\w+$~', $key)) { + return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__); + } + $key_part = "\$this->_tpl_vars['$key'] => "; + } else { + $key = null; + $key_part = ''; + } + + if (isset($attrs['name'])) { + $name = $attrs['name']; + } else { + $name = null; + } + + $output = '_foreach[$name]"; + $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n"; + $output .= "if ({$foreach_props}['total'] > 0):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + $output .= " {$foreach_props}['iteration']++;\n"; + } else { + $output .= "if (count(\$_from)):\n"; + $output .= " foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n"; + } + $output .= '?>'; + + return $output; + } + + + /** + * Compile {capture} .. {/capture} tags + * + * @param boolean $start true if this is the {capture} tag + * @param string $tag_args + * @return string + */ + + function _compile_capture_tag($start, $tag_args = '') + { + $attrs = $this->_parse_attrs($tag_args); + + if ($start) { + if (isset($attrs['name'])) + $buffer = $attrs['name']; + else + $buffer = "'default'"; + + if (isset($attrs['assign'])) + $assign = $attrs['assign']; + else + $assign = null; + $output = ""; + $this->_capture_stack[] = array($buffer, $assign); + } else { + list($buffer, $assign) = array_pop($this->_capture_stack); + $output = "_smarty_vars['capture'][$buffer] = ob_get_contents(); "; + if (isset($assign)) { + $output .= " \$this->assign($assign, ob_get_contents());"; + } + $output .= "ob_end_clean(); ?>"; + } + + return $output; + } + + /** + * Compile {if ...} tag + * + * @param string $tag_args + * @param boolean $elseif if true, uses elseif instead of if + * @return string + */ + function _compile_if_tag($tag_args, $elseif = false) + { + + /* Tokenize args for 'if' tag. */ + preg_match_all('~(?> + ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call + ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)? | # var or quoted string + \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@ | # valid non-word token + \b\w+\b | # valid word token + \S+ # anything else + )~x', $tag_args, $match); + + $tokens = $match[0]; + + if(empty($tokens)) { + $_error_msg = $elseif ? "'elseif'" : "'if'"; + $_error_msg .= ' statement requires arguments'; + $this->_syntax_error($_error_msg, E_USER_ERROR, __FILE__, __LINE__); + } + + + // make sure we have balanced parenthesis + $token_count = array_count_values($tokens); + if(isset($token_count['(']) && $token_count['('] != $token_count[')']) { + $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + + $is_arg_stack = array(); + + for ($i = 0; $i < count($tokens); $i++) { + + $token = &$tokens[$i]; + + switch (strtolower($token)) { + case '!': + case '%': + case '!==': + case '==': + case '===': + case '>': + case '<': + case '!=': + case '<>': + case '<<': + case '>>': + case '<=': + case '>=': + case '&&': + case '||': + case '|': + case '^': + case '&': + case '~': + case ')': + case ',': + case '+': + case '-': + case '*': + case '/': + case '@': + break; + + case 'eq': + $token = '=='; + break; + + case 'ne': + case 'neq': + $token = '!='; + break; + + case 'lt': + $token = '<'; + break; + + case 'le': + case 'lte': + $token = '<='; + break; + + case 'gt': + $token = '>'; + break; + + case 'ge': + case 'gte': + $token = '>='; + break; + + case 'and': + $token = '&&'; + break; + + case 'or': + $token = '||'; + break; + + case 'not': + $token = '!'; + break; + + case 'mod': + $token = '%'; + break; + + case '(': + array_push($is_arg_stack, $i); + break; + + case 'is': + /* If last token was a ')', we operate on the parenthesized + expression. The start of the expression is on the stack. + Otherwise, we operate on the last encountered token. */ + if ($tokens[$i-1] == ')') + $is_arg_start = array_pop($is_arg_stack); + else + $is_arg_start = $i-1; + /* Construct the argument for 'is' expression, so it knows + what to operate on. */ + $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); + + /* Pass all tokens from next one until the end to the + 'is' expression parsing function. The function will + return modified tokens, where the first one is the result + of the 'is' expression and the rest are the tokens it + didn't touch. */ + $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); + + /* Replace the old tokens with the new ones. */ + array_splice($tokens, $is_arg_start, count($tokens), $new_tokens); + + /* Adjust argument start so that it won't change from the + current position for the next iteration. */ + $i = $is_arg_start; + break; + + default: + if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) { + // function call + if($this->security && + !in_array($token, $this->security_settings['IF_FUNCS'])) { + $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } + } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && (strpos('+-*/^%&|', substr($token, -1)) === false) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') { + // variable function call + $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__); + } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) { + // object or variable + $token = $this->_parse_var_props($token); + } elseif(is_numeric($token)) { + // number, skip it + } else { + $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + } + } + + if ($elseif) + return ''; + else + return ''; + } + + + function _compile_arg_list($type, $name, $attrs, &$cache_code) { + $arg_list = array(); + + if (isset($type) && isset($name) + && isset($this->_plugins[$type]) + && isset($this->_plugins[$type][$name]) + && empty($this->_plugins[$type][$name][4]) + && is_array($this->_plugins[$type][$name][5]) + ) { + /* we have a list of parameters that should be cached */ + $_cache_attrs = $this->_plugins[$type][$name][5]; + $_count = $this->_cache_attrs_count++; + $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');"; + + } else { + /* no parameters are cached */ + $_cache_attrs = null; + } + + foreach ($attrs as $arg_name => $arg_value) { + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + if (is_null($arg_value)) + $arg_value = 'null'; + if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) { + $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)"; + } else { + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + return $arg_list; + } + + /** + * Parse is expression + * + * @param string $is_arg + * @param array $tokens + * @return array + */ + function _parse_is_expr($is_arg, $tokens) + { + $expr_end = 0; + $negate_expr = false; + + if (($first_token = array_shift($tokens)) == 'not') { + $negate_expr = true; + $expr_type = array_shift($tokens); + } else + $expr_type = $first_token; + + switch ($expr_type) { + case 'even': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))"; + } else + $expr = "!(1 & $is_arg)"; + break; + + case 'odd': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))"; + } else + $expr = "(1 & $is_arg)"; + break; + + case 'div': + if (@$tokens[$expr_end] == 'by') { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")"; + } else { + $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__); + } + break; + + default: + $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if ($negate_expr) { + $expr = "!($expr)"; + } + + array_splice($tokens, 0, $expr_end, $expr); + + return $tokens; + } + + + /** + * Parse attribute string + * + * @param string $tag_args + * @return array + */ + function _parse_attrs($tag_args) + { + + /* Tokenize tag attributes. */ + preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+) + )+ | + [=] + ~x', $tag_args, $match); + $tokens = $match[0]; + + $attrs = array(); + /* Parse state: + 0 - expecting attribute name + 1 - expecting '=' + 2 - expecting attribute value (not '=') */ + $state = 0; + + foreach ($tokens as $token) { + switch ($state) { + case 0: + /* If the token is a valid identifier, we set attribute name + and go to state 1. */ + if (preg_match('~^\w+$~', $token)) { + $attr_name = $token; + $state = 1; + } else + $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 1: + /* If the token is '=', then we go to state 2. */ + if ($token == '=') { + $state = 2; + } else + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + break; + + case 2: + /* If token is not '=', we set the attribute value and go to + state 0. */ + if ($token != '=') { + /* We booleanize the token if it's a non-quoted possible + boolean value. */ + if (preg_match('~^(on|yes|true)$~', $token)) { + $token = 'true'; + } else if (preg_match('~^(off|no|false)$~', $token)) { + $token = 'false'; + } else if ($token == 'null') { + $token = 'null'; + } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) { + /* treat integer literally */ + } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) { + /* treat as a string, double-quote it escaping quotes */ + $token = '"'.addslashes($token).'"'; + } + + $attrs[$attr_name] = $token; + $state = 0; + } else + $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__); + break; + } + $last_token = $token; + } + + if($state != 0) { + if($state == 1) { + $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__); + } else { + $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } + + $this->_parse_vars_props($attrs); + + return $attrs; + } + + /** + * compile multiple variables and section properties tokens into + * PHP code + * + * @param array $tokens + */ + function _parse_vars_props(&$tokens) + { + foreach($tokens as $key => $val) { + $tokens[$key] = $this->_parse_var_props($val); + } + } + + /** + * compile single variable and section properties token into + * PHP code + * + * @param string $val + * @param string $tag_attrs + * @return string + */ + function _parse_var_props($val) + { + $val = trim($val); + + if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) { + // $ variable or object + $return = $this->_parse_var($match[1]); + $modifiers = $match[2]; + if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) { + $_default_mod_string = implode('|',(array)$this->default_modifiers); + $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers; + } + $this->_parse_modifiers($return, $modifiers); + return $return; + } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // double quoted text + preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + $return = $this->_expand_quoted_text($match[1]); + if($match[2] != '') { + $this->_parse_modifiers($return, $match[2]); + } + return $return; + } + elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // numerical constant + preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + if($match[2] != '') { + $this->_parse_modifiers($match[1], $match[2]); + return $match[1]; + } + } + elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // single quoted text + preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match); + if($match[2] != '') { + $this->_parse_modifiers($match[1], $match[2]); + return $match[1]; + } + } + elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // config var + return $this->_parse_conf_var($val); + } + elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) { + // section var + return $this->_parse_section_prop($val); + } + elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) { + // literal string + return $this->_expand_quoted_text('"' . strtr($val, array('\\' => '\\\\', '"' => '\\"')) .'"'); + } + return $val; + } + + /** + * expand quoted text with embedded variables + * + * @param string $var_expr + * @return string + */ + function _expand_quoted_text($var_expr) + { + // if contains unescaped $, expand it + if(preg_match_all('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?_parse_var(str_replace('`','',$_var)) . ')."'; + } + $var_expr = strtr($var_expr, $_replace); + $_return = preg_replace('~\.""|(?_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE); + + if(count($_math_vars) > 1) { + $_first_var = ""; + $_complete_var = ""; + $_output = ""; + // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter) + foreach($_math_vars as $_k => $_math_var) { + $_math_var = $_math_vars[$_k]; + + if(!empty($_math_var) || is_numeric($_math_var)) { + // hit a math operator, so process the stuff which came before it + if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) { + $_has_math = true; + if(!empty($_complete_var) || is_numeric($_complete_var)) { + $_output .= $this->_parse_var($_complete_var); + } + + // just output the math operator to php + $_output .= $_math_var; + + if(empty($_first_var)) + $_first_var = $_complete_var; + + $_complete_var = ""; + } else { + $_complete_var .= $_math_var; + } + } + } + if($_has_math) { + if(!empty($_complete_var) || is_numeric($_complete_var)) + $_output .= $this->_parse_var($_complete_var); + + // get the modifiers working (only the last var from math + modifier is left) + $var_expr = $_complete_var; + } + } + + // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit) + if(is_numeric(substr($var_expr, 0, 1))) + $_var_ref = $var_expr; + else + $_var_ref = substr($var_expr, 1); + + if(!$_has_math) { + + // get [foo] and .foo and ->foo and (...) pieces + preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match); + + $_indexes = $match[0]; + $_var_name = array_shift($_indexes); + + /* Handle $smarty.* variable references as a special case. */ + if ($_var_name == 'smarty') { + /* + * If the reference could be compiled, use the compiled output; + * otherwise, fall back on the $smarty variable generated at + * run-time. + */ + if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) { + $_output = $smarty_ref; + } else { + $_var_name = substr(array_shift($_indexes), 1); + $_output = "\$this->_smarty_vars['$_var_name']"; + } + } elseif(is_numeric($_var_name) && is_numeric(substr($var_expr, 0, 1))) { + // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers + if(count($_indexes) > 0) + { + $_var_name .= implode("", $_indexes); + $_indexes = array(); + } + $_output = $_var_name; + } else { + $_output = "\$this->_tpl_vars['$_var_name']"; + } + + foreach ($_indexes as $_index) { + if (substr($_index, 0, 1) == '[') { + $_index = substr($_index, 1, -1); + if (is_numeric($_index)) { + $_output .= "[$_index]"; + } elseif (substr($_index, 0, 1) == '$') { + if (strpos($_index, '.') !== false) { + $_output .= '[' . $this->_parse_var($_index) . ']'; + } else { + $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]"; + } + } else { + $_var_parts = explode('.', $_index); + $_var_section = $_var_parts[0]; + $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index'; + $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]"; + } + } else if (substr($_index, 0, 1) == '.') { + if (substr($_index, 1, 1) == '$') + $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]"; + else + $_output .= "['" . substr($_index, 1) . "']"; + } else if (substr($_index,0,2) == '->') { + if(substr($_index,2,2) == '__') { + $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif($this->security && substr($_index, 2, 1) == '_') { + $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } elseif (substr($_index, 2, 1) == '$') { + if ($this->security) { + $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__); + } else { + $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}'; + } + } else { + $_output .= $_index; + } + } elseif (substr($_index, 0, 1) == '(') { + $_index = $this->_parse_parenth_args($_index); + $_output .= $_index; + } else { + $_output .= $_index; + } + } + } + + return $_output; + } + + /** + * parse arguments in function call parenthesis + * + * @param string $parenth_args + * @return string + */ + function _parse_parenth_args($parenth_args) + { + preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match); + $orig_vals = $match = $match[0]; + $this->_parse_vars_props($match); + $replace = array(); + for ($i = 0, $count = count($match); $i < $count; $i++) { + $replace[$orig_vals[$i]] = $match[$i]; + } + return strtr($parenth_args, $replace); + } + + /** + * parse configuration variable expression into PHP code + * + * @param string $conf_var_expr + */ + function _parse_conf_var($conf_var_expr) + { + $parts = explode('|', $conf_var_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + $var_name = substr($var_ref, 1, -1); + + $output = "\$this->_config[0]['vars']['$var_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + /** + * parse section property expression into PHP code + * + * @param string $section_prop_expr + * @return string + */ + function _parse_section_prop($section_prop_expr) + { + $parts = explode('|', $section_prop_expr, 2); + $var_ref = $parts[0]; + $modifiers = isset($parts[1]) ? $parts[1] : ''; + + preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match); + $section_name = $match[1]; + $prop_name = $match[2]; + + $output = "\$this->_sections['$section_name']['$prop_name']"; + + $this->_parse_modifiers($output, $modifiers); + + return $output; + } + + + /** + * parse modifier chain into PHP code + * + * sets $output to parsed modified chain + * @param string $output + * @param string $modifier_string + */ + function _parse_modifiers(&$output, $modifier_string) + { + preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match); + list(, $_modifiers, $modifier_arg_strings) = $_match; + + for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) { + $_modifier_name = $_modifiers[$_i]; + + if($_modifier_name == 'smarty') { + // skip smarty modifier + continue; + } + + preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match); + $_modifier_args = $_match[1]; + + if (substr($_modifier_name, 0, 1) == '@') { + $_map_array = false; + $_modifier_name = substr($_modifier_name, 1); + } else { + $_map_array = true; + } + + if (empty($this->_plugins['modifier'][$_modifier_name]) + && !$this->_get_plugin_filepath('modifier', $_modifier_name) + && function_exists($_modifier_name)) { + if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) { + $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__); + } else { + $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name, null, null, false); + } + } + $this->_add_plugin('modifier', $_modifier_name); + + $this->_parse_vars_props($_modifier_args); + + if($_modifier_name == 'default') { + // supress notifications of default modifier vars and args + if(substr($output, 0, 1) == '$') { + $output = '@' . $output; + } + if(isset($_modifier_args[0]) && substr($_modifier_args[0], 0, 1) == '$') { + $_modifier_args[0] = '@' . $_modifier_args[0]; + } + } + if (count($_modifier_args) > 0) + $_modifier_args = ', '.implode(', ', $_modifier_args); + else + $_modifier_args = ''; + + if ($_map_array) { + $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))"; + + } else { + + $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)"; + + } + } + } + + + /** + * add plugin + * + * @param string $type + * @param string $name + * @param boolean? $delayed_loading + */ + function _add_plugin($type, $name, $delayed_loading = null) + { + if (!isset($this->_plugin_info[$type])) { + $this->_plugin_info[$type] = array(); + } + if (!isset($this->_plugin_info[$type][$name])) { + $this->_plugin_info[$type][$name] = array($this->_current_file, + $this->_current_line_no, + $delayed_loading); + } + } + + + /** + * Compiles references of type $smarty.foo + * + * @param string $indexes + * @return string + */ + function _compile_smarty_ref(&$indexes) + { + /* Extract the reference name. */ + $_ref = substr($indexes[0], 1); + foreach($indexes as $_index_no=>$_index) { + if (substr($_index, 0, 1) != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) { + $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + } + + switch ($_ref) { + case 'now': + $compiled_ref = 'time()'; + $_max_index = 1; + break; + + case 'foreach': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $_propname = substr($indexes[1], 1); + $_max_index = 1; + switch ($_propname) { + case 'index': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)"; + break; + + case 'first': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)"; + break; + + case 'last': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])"; + break; + + case 'show': + array_shift($indexes); + $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)"; + break; + + default: + unset($_max_index); + $compiled_ref = "\$this->_foreach[$_var]"; + } + break; + + case 'section': + array_shift($indexes); + $_var = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = "\$this->_sections[$_var]"; + break; + + case 'get': + $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']"; + break; + + case 'post': + $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']"; + break; + + case 'cookies': + $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']"; + break; + + case 'env': + $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']"; + break; + + case 'server': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']"; + break; + + case 'session': + $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']"; + break; + + /* + * These cases are handled either at run-time or elsewhere in the + * compiler. + */ + case 'request': + if ($this->request_use_auto_globals) { + $compiled_ref = '$_REQUEST'; + break; + } else { + $this->_init_smarty_vars = true; + } + return null; + + case 'capture': + return null; + + case 'template': + $compiled_ref = "'$this->_current_file'"; + $_max_index = 1; + break; + + case 'version': + $compiled_ref = "'$this->_version'"; + $_max_index = 1; + break; + + case 'const': + if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) { + $this->_syntax_error("(secure mode) constants not permitted", + E_USER_WARNING, __FILE__, __LINE__); + return; + } + array_shift($indexes); + if (preg_match('!^\.\w+$!', $indexes[0])) { + $compiled_ref = '@' . substr($indexes[0], 1); + } else { + $_val = $this->_parse_var_props(substr($indexes[0], 1)); + $compiled_ref = '@constant(' . $_val . ')'; + } + $_max_index = 1; + break; + + case 'config': + $compiled_ref = "\$this->_config[0]['vars']"; + $_max_index = 3; + break; + + case 'ldelim': + $compiled_ref = "'$this->left_delimiter'"; + break; + + case 'rdelim': + $compiled_ref = "'$this->right_delimiter'"; + break; + + default: + $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__); + break; + } + + if (isset($_max_index) && count($indexes) > $_max_index) { + $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__); + } + + array_shift($indexes); + return $compiled_ref; + } + + /** + * compiles call to plugin of type $type with name $name + * returns a string containing the function-name or method call + * without the paramter-list that would have follow to make the + * call valid php-syntax + * + * @param string $type + * @param string $name + * @return string + */ + function _compile_plugin_call($type, $name) { + if (isset($this->_plugins[$type][$name])) { + /* plugin loaded */ + if (is_array($this->_plugins[$type][$name][0])) { + return ((is_object($this->_plugins[$type][$name][0][0])) ? + "\$this->_plugins['$type']['$name'][0][0]->" /* method callback */ + : (string)($this->_plugins[$type][$name][0][0]).'::' /* class callback */ + ). $this->_plugins[$type][$name][0][1]; + + } else { + /* function callback */ + return $this->_plugins[$type][$name][0]; + + } + } else { + /* plugin not loaded -> auto-loadable-plugin */ + return 'smarty_'.$type.'_'.$name; + + } + } + + /** + * load pre- and post-filters + */ + function _load_filters() + { + if (count($this->_plugins['prefilter']) > 0) { + foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) { + if ($prefilter === false) { + unset($this->_plugins['prefilter'][$filter_name]); + $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + if (count($this->_plugins['postfilter']) > 0) { + foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) { + if ($postfilter === false) { + unset($this->_plugins['postfilter'][$filter_name]); + $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false))); + require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); + smarty_core_load_plugins($_params, $this); + } + } + } + } + + + /** + * Quote subpattern references + * + * @param string $string + * @return string + */ + function _quote_replace($string) + { + return strtr($string, array('\\' => '\\\\', '$' => '\\$')); + } + + /** + * display Smarty syntax error + * + * @param string $error_msg + * @param integer $error_type + * @param string $file + * @param integer $line + */ + function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null) + { + $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type); + } + + + /** + * check if the compilation changes from cacheable to + * non-cacheable state with the beginning of the current + * plugin. return php-code to reflect the transition. + * @return string + */ + function _push_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || 0<$this->_cacheable_state++) return ''; + if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty')); + $_ret = 'if ($this->caching && !$this->_cache_including): echo \'{nocache:' + . $this->_cache_serial . '#' . $this->_nocache_count + . '}\'; endif;'; + return $_ret; + } + + + /** + * check if the compilation changes from non-cacheable to + * cacheable state with the end of the current plugin return + * php-code to reflect the transition. + * @return string + */ + function _pop_cacheable_state($type, $name) { + $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4]; + if ($_cacheable + || --$this->_cacheable_state>0) return ''; + return 'if ($this->caching && !$this->_cache_including): echo \'{/nocache:' + . $this->_cache_serial . '#' . ($this->_nocache_count++) + . '}\'; endif;'; + } + + + /** + * push opening tag-name, file-name and line-number on the tag-stack + * @param string the opening tag's name + */ + function _push_tag($open_tag) + { + array_push($this->_tag_stack, array($open_tag, $this->_current_line_no)); + } + + /** + * pop closing tag-name + * raise an error if this stack-top doesn't match with the closing tag + * @param string the closing tag's name + * @return string the opening tag's name + */ + function _pop_tag($close_tag) + { + $message = ''; + if (count($this->_tag_stack)>0) { + list($_open_tag, $_line_no) = array_pop($this->_tag_stack); + if ($close_tag == $_open_tag) { + return $_open_tag; + } + if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) { + return $this->_pop_tag($close_tag); + } + if ($close_tag == 'section' && $_open_tag == 'sectionelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') { + $this->_pop_tag($close_tag); + return $_open_tag; + } + if ($_open_tag == 'else' || $_open_tag == 'elseif') { + $_open_tag = 'if'; + } elseif ($_open_tag == 'sectionelse') { + $_open_tag = 'section'; + } elseif ($_open_tag == 'foreachelse') { + $_open_tag = 'foreach'; + } + $message = " expected {/$_open_tag} (opened line $_line_no)."; + } + $this->_syntax_error("mismatched tag {/$close_tag}.$message", + E_USER_ERROR, __FILE__, __LINE__); + } + +} + +/** + * compare to values by their string length + * + * @access private + * @param string $a + * @param string $b + * @return 0|-1|1 + */ +function _smarty_sort_length($a, $b) +{ + if($a == $b) + return 0; + + if(strlen($a) == strlen($b)) + return ($a > $b) ? -1 : 1; + + return (strlen($a) > strlen($b)) ? -1 : 1; +} + + +/* vim: set et: */ + +?> diff --git a/Tools/projectGenerator/smarty/debug.tpl b/Tools/projectGenerator/smarty/debug.tpl new file mode 100644 index 000000000..c05ef5d0b --- /dev/null +++ b/Tools/projectGenerator/smarty/debug.tpl @@ -0,0 +1,157 @@ +{* Smarty *} +{* debug.tpl, last updated version 2.1.0 *} +{assign_debug_info} +{capture assign=debug_output} + + + + Smarty Debug Console +{literal} + +{/literal} + + + +

Smarty Debug Console

+ +

included templates & config files (load time in seconds)

+ +
+{section name=templates loop=$_debug_tpls} + {section name=indent loop=$_debug_tpls[templates].depth}   {/section} + + {$_debug_tpls[templates].filename|escape:html} + {if isset($_debug_tpls[templates].exec_time)} + + ({$_debug_tpls[templates].exec_time|string_format:"%.5f"}) + {if %templates.index% eq 0}(total){/if} + + {/if} +
+{sectionelse} +

no templates included

+{/section} +
+ +

assigned template variables

+ + + {section name=vars loop=$_debug_keys} + + + + {sectionelse} + + {/section} +
{ldelim}${$_debug_keys[vars]|escape:'html'}{rdelim}{$_debug_vals[vars]|@debug_print_var}

no template variables assigned

+ +

assigned config file variables (outer template scope)

+ + + {section name=config_vars loop=$_debug_config_keys} + + + + {sectionelse} + + {/section} +
{ldelim}#{$_debug_config_keys[config_vars]|escape:'html'}#{rdelim}{$_debug_config_vals[config_vars]|@debug_print_var}

no config vars assigned

+ + +{/capture} +{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"} + {$debug_output} +{else} + +{/if} \ No newline at end of file diff --git a/Tools/projectGenerator/smarty/internals/core.assemble_plugin_filepath.php b/Tools/projectGenerator/smarty/internals/core.assemble_plugin_filepath.php new file mode 100644 index 000000000..690d3ddbc --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.assemble_plugin_filepath.php @@ -0,0 +1,67 @@ +plugins_dir as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + // see if path is relative + if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) { + $_relative_paths[] = $_plugin_dir; + // relative path, see if it is in the SMARTY_DIR + if (@is_readable(SMARTY_DIR . $_plugin_filepath)) { + $_return = SMARTY_DIR . $_plugin_filepath; + break; + } + } + // try relative to cwd (or absolute) + if (@is_readable($_plugin_filepath)) { + $_return = $_plugin_filepath; + break; + } + } + + if($_return === false) { + // still not found, try PHP include_path + if(isset($_relative_paths)) { + foreach ((array)$_relative_paths as $_plugin_dir) { + + $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename; + + $_params = array('file_path' => $_plugin_filepath); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_return = $_params['new_file_path']; + break; + } + } + } + } + $_filepaths_cache[$_plugin_filename] = $_return; + return $_return; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.assign_smarty_interface.php b/Tools/projectGenerator/smarty/internals/core.assign_smarty_interface.php new file mode 100644 index 000000000..7e65a73ec --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.assign_smarty_interface.php @@ -0,0 +1,43 @@ + + * Name: assign_smarty_interface
+ * Purpose: assign the $smarty interface variable + * @param array Format: null + * @param Smarty + */ +function smarty_core_assign_smarty_interface($params, &$smarty) +{ + if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) { + return; + } + + $_globals_map = array('g' => 'HTTP_GET_VARS', + 'p' => 'HTTP_POST_VARS', + 'c' => 'HTTP_COOKIE_VARS', + 's' => 'HTTP_SERVER_VARS', + 'e' => 'HTTP_ENV_VARS'); + + $_smarty_vars_request = array(); + + foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) { + if (isset($_globals_map[$_c])) { + $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]); + } + } + $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']); + + $smarty->_smarty_vars['request'] = $_smarty_vars_request; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.create_dir_structure.php b/Tools/projectGenerator/smarty/internals/core.create_dir_structure.php new file mode 100644 index 000000000..3eecc4972 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.create_dir_structure.php @@ -0,0 +1,79 @@ +_dir_perms) && !is_dir($_new_dir)) { + $smarty->trigger_error("problem creating directory '" . $_new_dir . "'"); + return false; + } + $_new_dir .= '/'; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.display_debug_console.php b/Tools/projectGenerator/smarty/internals/core.display_debug_console.php new file mode 100644 index 000000000..1a80f3909 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.display_debug_console.php @@ -0,0 +1,61 @@ + + * Name: display_debug_console
+ * Purpose: display the javascript debug console window + * @param array Format: null + * @param Smarty + */ +function smarty_core_display_debug_console($params, &$smarty) +{ + // we must force compile the debug template in case the environment + // changed between separate applications. + + if(empty($smarty->debug_tpl)) { + // set path to debug template from SMARTY_DIR + $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl'; + if($smarty->security && is_file($smarty->debug_tpl)) { + $smarty->secure_dir[] = realpath($smarty->debug_tpl); + } + $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl'; + } + + $_ldelim_orig = $smarty->left_delimiter; + $_rdelim_orig = $smarty->right_delimiter; + + $smarty->left_delimiter = '{'; + $smarty->right_delimiter = '}'; + + $_compile_id_orig = $smarty->_compile_id; + $smarty->_compile_id = null; + + $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl); + if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path)) + { + ob_start(); + $smarty->_include($_compile_path); + $_results = ob_get_contents(); + ob_end_clean(); + } else { + $_results = ''; + } + + $smarty->_compile_id = $_compile_id_orig; + + $smarty->left_delimiter = $_ldelim_orig; + $smarty->right_delimiter = $_rdelim_orig; + + return $_results; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.get_include_path.php b/Tools/projectGenerator/smarty/internals/core.get_include_path.php new file mode 100644 index 000000000..43432412b --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.get_include_path.php @@ -0,0 +1,44 @@ + diff --git a/Tools/projectGenerator/smarty/internals/core.get_microtime.php b/Tools/projectGenerator/smarty/internals/core.get_microtime.php new file mode 100644 index 000000000..f1a28e042 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.get_microtime.php @@ -0,0 +1,23 @@ + diff --git a/Tools/projectGenerator/smarty/internals/core.get_php_resource.php b/Tools/projectGenerator/smarty/internals/core.get_php_resource.php new file mode 100644 index 000000000..786d4e78e --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.get_php_resource.php @@ -0,0 +1,80 @@ +trusted_dir; + $smarty->_parse_resource_name($params, $smarty); + + /* + * Find out if the resource exists. + */ + + if ($params['resource_type'] == 'file') { + $_readable = false; + if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) { + $_readable = true; + } else { + // test for file in include_path + $_params = array('file_path' => $params['resource_name']); + require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); + if(smarty_core_get_include_path($_params, $smarty)) { + $_include_path = $_params['new_file_path']; + $_readable = true; + } + } + } else if ($params['resource_type'] != 'file') { + $_template_source = null; + $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0]) + && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0], + array($params['resource_name'], &$_template_source, &$smarty)); + } + + /* + * Set the error function, depending on which class calls us. + */ + if (method_exists($smarty, '_syntax_error')) { + $_error_funcc = '_syntax_error'; + } else { + $_error_funcc = 'trigger_error'; + } + + if ($_readable) { + if ($smarty->security) { + require_once(SMARTY_CORE_DIR . 'core.is_trusted.php'); + if (!smarty_core_is_trusted($params, $smarty)) { + $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted'); + return false; + } + } + } else { + $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable'); + return false; + } + + if ($params['resource_type'] == 'file') { + $params['php_resource'] = $params['resource_name']; + } else { + $params['php_resource'] = $_template_source; + } + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.is_secure.php b/Tools/projectGenerator/smarty/internals/core.is_secure.php new file mode 100644 index 000000000..d54abd432 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.is_secure.php @@ -0,0 +1,59 @@ +security || $smarty->security_settings['INCLUDE_ANY']) { + return true; + } + + if ($params['resource_type'] == 'file') { + $_rp = realpath($params['resource_name']); + if (isset($params['resource_base_path'])) { + foreach ((array)$params['resource_base_path'] as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false && + strncmp($_rp, $_cd, strlen($_cd)) == 0 && + substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { + return true; + } + } + } + if (!empty($smarty->secure_dir)) { + foreach ((array)$smarty->secure_dir as $curr_dir) { + if ( ($_cd = realpath($curr_dir)) !== false) { + if($_cd == $_rp) { + return true; + } elseif (strncmp($_rp, $_cd, strlen($_cd)) == 0 && + substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR) { + return true; + } + } + } + } + } else { + // resource is not on local file system + return call_user_func_array( + $smarty->_plugins['resource'][$params['resource_type']][0][2], + array($params['resource_name'], &$smarty)); + } + + return false; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.is_trusted.php b/Tools/projectGenerator/smarty/internals/core.is_trusted.php new file mode 100644 index 000000000..429973158 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.is_trusted.php @@ -0,0 +1,47 @@ +trusted_dir)) { + $_rp = realpath($params['resource_name']); + foreach ((array)$smarty->trusted_dir as $curr_dir) { + if (!empty($curr_dir) && is_readable ($curr_dir)) { + $_cd = realpath($curr_dir); + if (strncmp($_rp, $_cd, strlen($_cd)) == 0 + && substr($_rp, strlen($_cd), 1) == DIRECTORY_SEPARATOR ) { + $_smarty_trusted = true; + break; + } + } + } + } + + } else { + // resource is not on local file system + $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3], + array($params['resource_name'], $smarty)); + } + + return $_smarty_trusted; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.load_plugins.php b/Tools/projectGenerator/smarty/internals/core.load_plugins.php new file mode 100644 index 000000000..6db1dc51d --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.load_plugins.php @@ -0,0 +1,125 @@ +_plugins[$_type][$_name]; + + /* + * We do not load plugin more than once for each instance of Smarty. + * The following code checks for that. The plugin can also be + * registered dynamically at runtime, in which case template file + * and line number will be unknown, so we fill them in. + * + * The final element of the info array is a flag that indicates + * whether the dynamically registered plugin function has been + * checked for existence yet or not. + */ + if (isset($_plugin)) { + if (empty($_plugin[3])) { + if (!is_callable($_plugin[0])) { + $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } else { + $_plugin[1] = $_tpl_file; + $_plugin[2] = $_tpl_line; + $_plugin[3] = true; + if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */ + } + } + continue; + } else if ($_type == 'insert') { + /* + * For backwards compatibility, we check for insert functions in + * the symbol table before trying to load them as a plugin. + */ + $_plugin_func = 'insert_' . $_name; + if (function_exists($_plugin_func)) { + $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false); + continue; + } + } + + $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name); + + if (! $_found = ($_plugin_file != false)) { + $_message = "could not load plugin file '$_type.$_name.php'\n"; + } + + /* + * If plugin file is found, it -must- provide the properly named + * plugin function. In case it doesn't, simply output the error and + * do not fall back on any other method. + */ + if ($_found) { + include_once $_plugin_file; + + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__); + continue; + } + } + /* + * In case of insert plugins, their code may be loaded later via + * 'script' attribute. + */ + else if ($_type == 'insert' && $_delayed_loading) { + $_plugin_func = 'smarty_' . $_type . '_' . $_name; + $_found = true; + } + + /* + * Plugin specific processing and error checking. + */ + if (!$_found) { + if ($_type == 'modifier') { + /* + * In case modifier falls back on using PHP functions + * directly, we only allow those specified in the security + * context. + */ + if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) { + $_message = "(secure mode) modifier '$_name' is not allowed"; + } else { + if (!function_exists($_name)) { + $_message = "modifier '$_name' is not implemented"; + } else { + $_plugin_func = $_name; + $_found = true; + } + } + } else if ($_type == 'function') { + /* + * This is a catch-all situation. + */ + $_message = "unknown tag - '$_name'"; + } + } + + if ($_found) { + $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true); + } else { + // output error + $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__); + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.load_resource_plugin.php b/Tools/projectGenerator/smarty/internals/core.load_resource_plugin.php new file mode 100644 index 000000000..a7d37d1af --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.load_resource_plugin.php @@ -0,0 +1,74 @@ +_plugins['resource'][$params['type']]; + if (isset($_plugin)) { + if (!$_plugin[1] && count($_plugin[0])) { + $_plugin[1] = true; + foreach ($_plugin[0] as $_plugin_func) { + if (!is_callable($_plugin_func)) { + $_plugin[1] = false; + break; + } + } + } + + if (!$_plugin[1]) { + $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__); + } + + return; + } + + $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']); + $_found = ($_plugin_file != false); + + if ($_found) { /* + * If the plugin file is found, it -must- provide the properly named + * plugin functions. + */ + include_once($_plugin_file); + + /* + * Locate functions that we require the plugin to provide. + */ + $_resource_ops = array('source', 'timestamp', 'secure', 'trusted'); + $_resource_funcs = array(); + foreach ($_resource_ops as $_op) { + $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op; + if (!function_exists($_plugin_func)) { + $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__); + return; + } else { + $_resource_funcs[] = $_plugin_func; + } + } + + $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true); + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.process_cached_inserts.php b/Tools/projectGenerator/smarty/internals/core.process_cached_inserts.php new file mode 100644 index 000000000..1d78edd93 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.process_cached_inserts.php @@ -0,0 +1,71 @@ +_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis', + $params['results'], $match); + list($cached_inserts, $insert_args) = $match; + + for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) { + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $args = unserialize($insert_args[$i]); + $name = $args['name']; + + if (isset($args['script'])) { + $_params = array('resource_name' => $smarty->_dequote($args['script'])); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + $resource_type = $_params['resource_type']; + $php_resource = $_params['php_resource']; + + + if ($resource_type == 'file') { + $smarty->_include($php_resource, true); + } else { + $smarty->_eval($php_resource); + } + } + + $function_name = $smarty->_plugins['insert'][$name][0]; + if (empty($args['assign'])) { + $replace = $function_name($args, $smarty); + } else { + $smarty->assign($args['assign'], $function_name($args, $smarty)); + $replace = ''; + } + + $params['results'] = substr_replace($params['results'], $replace, strpos($params['results'], $cached_inserts[$i]), strlen($cached_inserts[$i])); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$name, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time); + } + } + + return $params['results']; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.process_compiled_include.php b/Tools/projectGenerator/smarty/internals/core.process_compiled_include.php new file mode 100644 index 000000000..d539423bf --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.process_compiled_include.php @@ -0,0 +1,37 @@ +_cache_including; + $smarty->_cache_including = true; + + $_return = $params['results']; + + foreach ($smarty->_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) { + $smarty->_include($_include_file_path, true); + } + + foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) { + $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s', + array(&$smarty, '_process_compiled_include_callback'), + $_return); + } + $smarty->_cache_including = $_cache_including; + return $_return; +} + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.read_cache_file.php b/Tools/projectGenerator/smarty/internals/core.read_cache_file.php new file mode 100644 index 000000000..c60e113a7 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.read_cache_file.php @@ -0,0 +1,101 @@ +force_compile) { + // force compile enabled, always regenerate + return false; + } + + if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) { + list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']]; + return true; + } + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $params['results'] = $smarty->_read_file($_cache_file); + } + + if (empty($params['results'])) { + // nothing to parse (error?), regenerate cache + return false; + } + + $_contents = $params['results']; + $_info_start = strpos($_contents, "\n") + 1; + $_info_len = (int)substr($_contents, 0, $_info_start - 1); + $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len)); + $params['results'] = substr($_contents, $_info_start + $_info_len); + + if ($smarty->caching == 2 && isset ($_cache_info['expires'])){ + // caching by expiration time + if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) { + // cache expired, regenerate + return false; + } + } else { + // caching by lifetime + if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) { + // cache expired, regenerate + return false; + } + } + + if ($smarty->compile_check) { + $_params = array('get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['template']) as $_template_dep) { + $_params['resource_name'] = $_template_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // template file has changed, regenerate cache + return false; + } + } + + if (isset($_cache_info['config'])) { + $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true); + foreach (array_keys($_cache_info['config']) as $_config_dep) { + $_params['resource_name'] = $_config_dep; + if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) { + // config file has changed, regenerate cache + return false; + } + } + } + } + + $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info); + + $smarty->_cache_info = $_cache_info; + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.rm_auto.php b/Tools/projectGenerator/smarty/internals/core.rm_auto.php new file mode 100644 index 000000000..b251f6491 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.rm_auto.php @@ -0,0 +1,71 @@ + $params['auto_base'], + 'level' => 0, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']); + + if(isset($params['auto_source'])) { + if (isset($params['extensions'])) { + $_res = false; + foreach ((array)$params['extensions'] as $_extension) + $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']); + } else { + $_res = $smarty->_unlink($_tname, $params['exp_time']); + } + } elseif ($smarty->use_sub_dirs) { + $_params = array( + 'dirname' => $_tname, + 'level' => 1, + 'exp_time' => $params['exp_time'] + ); + require_once(SMARTY_CORE_DIR . 'core.rmdir.php'); + $_res = smarty_core_rmdir($_params, $smarty); + } else { + // remove matching file names + $_handle = opendir($params['auto_base']); + $_res = true; + while (false !== ($_filename = readdir($_handle))) { + if($_filename == '.' || $_filename == '..') { + continue; + } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) { + $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']); + } + } + } + } + + return $_res; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.rmdir.php b/Tools/projectGenerator/smarty/internals/core.rmdir.php new file mode 100644 index 000000000..2166c44d2 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.rmdir.php @@ -0,0 +1,54 @@ + keep root) + * WARNING: no tests, it will try to remove what you tell it! + * + * @param string $dirname + * @param integer $level + * @param integer $exp_time + * @return boolean + */ + +// $dirname, $level = 1, $exp_time = null + +function smarty_core_rmdir($params, &$smarty) +{ + if(!isset($params['level'])) { $params['level'] = 1; } + if(!isset($params['exp_time'])) { $params['exp_time'] = null; } + + if($_handle = @opendir($params['dirname'])) { + + while (false !== ($_entry = readdir($_handle))) { + if ($_entry != '.' && $_entry != '..') { + if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) { + $_params = array( + 'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry, + 'level' => $params['level'] + 1, + 'exp_time' => $params['exp_time'] + ); + smarty_core_rmdir($_params, $smarty); + } + else { + $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']); + } + } + } + closedir($_handle); + } + + if ($params['level']) { + return @rmdir($params['dirname']); + } + return (bool)$_handle; + +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.run_insert_handler.php b/Tools/projectGenerator/smarty/internals/core.run_insert_handler.php new file mode 100644 index 000000000..71c384508 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.run_insert_handler.php @@ -0,0 +1,71 @@ +debugging) { + $_params = array(); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + if ($smarty->caching) { + $_arg_string = serialize($params['args']); + $_name = $params['args']['name']; + if (!isset($smarty->_cache_info['insert_tags'][$_name])) { + $smarty->_cache_info['insert_tags'][$_name] = array('insert', + $_name, + $smarty->_plugins['insert'][$_name][1], + $smarty->_plugins['insert'][$_name][2], + !empty($params['args']['script']) ? true : false); + } + return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5; + } else { + if (isset($params['args']['script'])) { + $_params = array('resource_name' => $smarty->_dequote($params['args']['script'])); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + if(!smarty_core_get_php_resource($_params, $smarty)) { + return false; + } + + if ($_params['resource_type'] == 'file') { + $smarty->_include($_params['php_resource'], true); + } else { + $smarty->_eval($_params['php_resource']); + } + unset($params['args']['script']); + } + + $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0]; + $_content = $_funcname($params['args'], $smarty); + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'insert', + 'filename' => 'insert_'.$params['args']['name'], + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + + if (!empty($params['args']["assign"])) { + $smarty->assign($params['args']["assign"], $_content); + } else { + return $_content; + } + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.smarty_include_php.php b/Tools/projectGenerator/smarty/internals/core.smarty_include_php.php new file mode 100644 index 000000000..30c6e7654 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.smarty_include_php.php @@ -0,0 +1,50 @@ + $params['smarty_file']); + require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php'); + smarty_core_get_php_resource($_params, $smarty); + $_smarty_resource_type = $_params['resource_type']; + $_smarty_php_resource = $_params['php_resource']; + + if (!empty($params['smarty_assign'])) { + ob_start(); + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + $smarty->assign($params['smarty_assign'], ob_get_contents()); + ob_end_clean(); + } else { + if ($_smarty_resource_type == 'file') { + $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']); + } else { + $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']); + } + } +} + + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.write_cache_file.php b/Tools/projectGenerator/smarty/internals/core.write_cache_file.php new file mode 100644 index 000000000..72f785b74 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.write_cache_file.php @@ -0,0 +1,96 @@ +_cache_info['timestamp'] = time(); + if ($smarty->cache_lifetime > -1){ + // expiration set + $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime; + } else { + // cache will never expire + $smarty->_cache_info['expires'] = -1; + } + + // collapse nocache.../nocache-tags + if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) { + // remove everything between every pair of outermost noache.../nocache-tags + // and replace it by a single nocache-tag + // this new nocache-tag will be replaced by dynamic contents in + // smarty_core_process_compiled_includes() on a cache-read + + $match_count = count($match[0]); + $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE); + + $level = 0; + $j = 0; + for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) { + if ($results[$i] == $match[0][$j]) { + // nocache tag + if ($match[1][$j]) { // closing tag + $level--; + unset($results[$i]); + } else { // opening tag + if ($level++ > 0) unset($results[$i]); + } + $j++; + } elseif ($level > 0) { + unset($results[$i]); + } + } + $params['results'] = implode('', $results); + } + $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials; + + // prepend the cache header info into cache file + $_cache_info = serialize($smarty->_cache_info); + $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results']; + + if (!empty($smarty->cache_handler_func)) { + // use cache_handler function + call_user_func_array($smarty->cache_handler_func, + array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null)); + } else { + // use local cache file + + if(!@is_writable($smarty->cache_dir)) { + // cache_dir not writable, see if it exists + if(!@is_dir($smarty->cache_dir)) { + $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']); + $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id); + $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.write_compiled_include.php b/Tools/projectGenerator/smarty/internals/core.write_compiled_include.php new file mode 100644 index 000000000..c14adb5f4 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.write_compiled_include.php @@ -0,0 +1,91 @@ +caching && \!\$this->_cache_including\)\: echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\'; endif;'; + $_tag_end = 'if \(\$this->caching && \!\$this->_cache_including\)\: echo \'\{/nocache\:(\\2)#(\\3)\}\'; endif;'; + + preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us', + $params['compiled_content'], $_match_source, PREG_SET_ORDER); + + // no nocache-parts found: done + if (count($_match_source)==0) return; + + // convert the matched php-code to functions + $_include_compiled = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n"; + $_include_compiled .= " compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n"; + + $_compile_path = $params['include_file_path']; + + $smarty->_cache_serials[$_compile_path] = $params['cache_serial']; + $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>"; + + $_include_compiled .= $params['plugins_code']; + $_include_compiled .= "= 5.0) ? '_smarty' : 'this'; + for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) { + $_match =& $_match_source[$_i]; + $source = $_match[4]; + if ($this_varname == '_smarty') { + /* rename $this to $_smarty in the sourcecode */ + $tokens = token_get_all('\n"; + + $_params = array('filename' => $_compile_path, + 'contents' => $_include_compiled, 'create_dirs' => true); + + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.write_compiled_resource.php b/Tools/projectGenerator/smarty/internals/core.write_compiled_resource.php new file mode 100644 index 000000000..b902eff3c --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.write_compiled_resource.php @@ -0,0 +1,35 @@ +compile_dir)) { + // compile_dir not writable, see if it exists + if(!@is_dir($smarty->compile_dir)) { + $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR); + return false; + } + $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR); + return false; + } + + $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true); + require_once(SMARTY_CORE_DIR . 'core.write_file.php'); + smarty_core_write_file($_params, $smarty); + return true; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/internals/core.write_file.php b/Tools/projectGenerator/smarty/internals/core.write_file.php new file mode 100644 index 000000000..8a3a3b398 --- /dev/null +++ b/Tools/projectGenerator/smarty/internals/core.write_file.php @@ -0,0 +1,54 @@ + $_dirname); + require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php'); + smarty_core_create_dir_structure($_params, $smarty); + } + + // write to tmp file, then rename it to avoid file locking race condition + $_tmp_file = tempnam($_dirname, 'wrt'); + + if (!($fd = @fopen($_tmp_file, 'wb'))) { + $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt'); + if (!($fd = @fopen($_tmp_file, 'wb'))) { + $smarty->trigger_error("problem writing temporary file '$_tmp_file'"); + return false; + } + } + + fwrite($fd, $params['contents']); + fclose($fd); + + if (DIRECTORY_SEPARATOR == '\\' || !@rename($_tmp_file, $params['filename'])) { + // On platforms and filesystems that cannot overwrite with rename() + // delete the file before renaming it -- because windows always suffers + // this, it is short-circuited to avoid the initial rename() attempt + @unlink($params['filename']); + @rename($_tmp_file, $params['filename']); + } + @chmod($params['filename'], $smarty->_file_perms); + + return true; +} + +/* vim: set expandtab: */ + +?> \ No newline at end of file diff --git a/Tools/projectGenerator/smarty/plugins/block.textformat.php b/Tools/projectGenerator/smarty/plugins/block.textformat.php new file mode 100644 index 000000000..8cd010acb --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/block.textformat.php @@ -0,0 +1,103 @@ + + * Name: textformat
+ * Purpose: format text a certain way with preset styles + * or custom wrap/indent settings
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat} + * (Smarty online manual) + * @param array + *
+ * Params:   style: string (email)
+ *           indent: integer (0)
+ *           wrap: integer (80)
+ *           wrap_char string ("\n")
+ *           indent_char: string (" ")
+ *           wrap_boundary: boolean (true)
+ * 
+ * @author Monte Ohrt + * @param string contents of the block + * @param Smarty clever simulation of a method + * @return string string $content re-formatted + */ +function smarty_block_textformat($params, $content, &$smarty) +{ + if (is_null($content)) { + return; + } + + $style = null; + $indent = 0; + $indent_first = 0; + $indent_char = ' '; + $wrap = 80; + $wrap_char = "\n"; + $wrap_cut = false; + $assign = null; + + foreach ($params as $_key => $_val) { + switch ($_key) { + case 'style': + case 'indent_char': + case 'wrap_char': + case 'assign': + $$_key = (string)$_val; + break; + + case 'indent': + case 'indent_first': + case 'wrap': + $$_key = (int)$_val; + break; + + case 'wrap_cut': + $$_key = (bool)$_val; + break; + + default: + $smarty->trigger_error("textformat: unknown attribute '$_key'"); + } + } + + if ($style == 'email') { + $wrap = 72; + } + + // split into paragraphs + $_paragraphs = preg_split('![\r\n][\r\n]!',$content); + $_output = ''; + + for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) { + if ($_paragraphs[$_x] == '') { + continue; + } + // convert mult. spaces & special chars to single space + $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]); + // indent first line + if($indent_first > 0) { + $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x]; + } + // wordwrap sentences + $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut); + // indent lines + if($indent > 0) { + $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]); + } + } + $_output = implode($wrap_char . $wrap_char, $_paragraphs); + + return $assign ? $smarty->assign($assign, $_output) : $_output; + +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/compiler.assign.php b/Tools/projectGenerator/smarty/plugins/compiler.assign.php new file mode 100644 index 000000000..be1729850 --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/compiler.assign.php @@ -0,0 +1,40 @@ + + * Name: assign
+ * Purpose: assign a value to a template variable + * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign} + * (Smarty online manual) + * @author Monte Ohrt (initial author) + * @auther messju mohr (conversion to compiler function) + * @param string containing var-attribute and value-attribute + * @param Smarty_Compiler + */ +function smarty_compiler_assign($tag_attrs, &$compiler) +{ + $_params = $compiler->_parse_attrs($tag_attrs); + + if (!isset($_params['var'])) { + $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING); + return; + } + + if (!isset($_params['value'])) { + $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING); + return; + } + + return "\$this->assign({$_params['var']}, {$_params['value']});"; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.assign_debug_info.php b/Tools/projectGenerator/smarty/plugins/function.assign_debug_info.php new file mode 100644 index 000000000..654049876 --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.assign_debug_info.php @@ -0,0 +1,40 @@ + + * Name: assign_debug_info
+ * Purpose: assign debug info to the template
+ * @author Monte Ohrt + * @param array unused in this plugin, this plugin uses {@link Smarty::$_config}, + * {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info} + * @param Smarty + */ +function smarty_function_assign_debug_info($params, &$smarty) +{ + $assigned_vars = $smarty->_tpl_vars; + ksort($assigned_vars); + if (@is_array($smarty->_config[0])) { + $config_vars = $smarty->_config[0]; + ksort($config_vars); + $smarty->assign("_debug_config_keys", array_keys($config_vars)); + $smarty->assign("_debug_config_vals", array_values($config_vars)); + } + + $included_templates = $smarty->_smarty_debug_info; + + $smarty->assign("_debug_keys", array_keys($assigned_vars)); + $smarty->assign("_debug_vals", array_values($assigned_vars)); + + $smarty->assign("_debug_tpls", $included_templates); +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.config_load.php b/Tools/projectGenerator/smarty/plugins/function.config_load.php new file mode 100644 index 000000000..db89f638c --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.config_load.php @@ -0,0 +1,142 @@ + + * Name: config_load
+ * Purpose: load config file vars + * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load} + * (Smarty online manual) + * @author Monte Ohrt + * @author messju mohr (added use of resources) + * @param array Format: + *
+ * array('file' => required config file name,
+ *       'section' => optional config file section to load
+ *       'scope' => local/parent/global
+ *       'global' => overrides scope, setting to parent if true)
+ * 
+ * @param Smarty + */ +function smarty_function_config_load($params, &$smarty) +{ + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $_debug_start_time = smarty_core_get_microtime($_params, $smarty); + } + + $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null; + $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null; + $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global'; + $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false; + + if (!isset($_file) || strlen($_file) == 0) { + $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__); + } + + if (isset($_scope)) { + if ($_scope != 'local' && + $_scope != 'parent' && + $_scope != 'global') { + $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__); + } + } else { + if ($_global) { + $_scope = 'parent'; + } else { + $_scope = 'local'; + } + } + + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + 'get_source' => false); + $smarty->_parse_resource_name($_params); + $_file_path = $_params['resource_type'] . ':' . $_params['resource_name']; + if (isset($_section)) + $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section); + else + $_compile_file = $smarty->_get_compile_path($_file_path); + + if($smarty->force_compile || !file_exists($_compile_file)) { + $_compile = true; + } elseif ($smarty->compile_check) { + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + 'get_source' => false); + $_compile = $smarty->_fetch_resource_info($_params) && + $_params['resource_timestamp'] > filemtime($_compile_file); + } else { + $_compile = false; + } + + if($_compile) { + // compile config file + if(!is_object($smarty->_conf_obj)) { + require_once SMARTY_DIR . $smarty->config_class . '.class.php'; + $smarty->_conf_obj = new $smarty->config_class(); + $smarty->_conf_obj->overwrite = $smarty->config_overwrite; + $smarty->_conf_obj->booleanize = $smarty->config_booleanize; + $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden; + $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines; + } + + $_params = array('resource_name' => $_file, + 'resource_base_path' => $smarty->config_dir, + $_params['get_source'] = true); + if (!$smarty->_fetch_resource_info($_params)) { + return; + } + $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']); + $_config_vars = array_merge($smarty->_conf_obj->get($_file), + $smarty->_conf_obj->get($_file, $_section)); + if(function_exists('var_export')) { + $_output = ''; + } else { + $_output = ''\\\'', '\\'=>'\\\\')) . '\'); ?>'; + } + $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp'])); + require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); + smarty_core_write_compiled_resource($_params, $smarty); + } else { + include($_compile_file); + } + + if ($smarty->caching) { + $smarty->_cache_info['config'][$_file] = true; + } + + $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars); + $smarty->_config[0]['files'][$_file] = true; + + if ($_scope == 'parent') { + $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars); + $smarty->_config[1]['files'][$_file] = true; + } else if ($_scope == 'global') { + for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) { + $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars); + $smarty->_config[$i]['files'][$_file] = true; + } + } + + if ($smarty->debugging) { + $_params = array(); + require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); + $smarty->_smarty_debug_info[] = array('type' => 'config', + 'filename' => $_file.' ['.$_section.'] '.$_scope, + 'depth' => $smarty->_inclusion_depth, + 'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time); + } + +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.counter.php b/Tools/projectGenerator/smarty/plugins/function.counter.php new file mode 100644 index 000000000..1f26db5fb --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.counter.php @@ -0,0 +1,80 @@ + + * Name: counter
+ * Purpose: print out a counter value + * @author Monte Ohrt + * @link http://smarty.php.net/manual/en/language.function.counter.php {counter} + * (Smarty online manual) + * @param array parameters + * @param Smarty + * @return string|null + */ +function smarty_function_counter($params, &$smarty) +{ + static $counters = array(); + + $name = (isset($params['name'])) ? $params['name'] : 'default'; + if (!isset($counters[$name])) { + $counters[$name] = array( + 'start'=>1, + 'skip'=>1, + 'direction'=>'up', + 'count'=>1 + ); + } + $counter =& $counters[$name]; + + if (isset($params['start'])) { + $counter['start'] = $counter['count'] = (int)$params['start']; + } + + if (!empty($params['assign'])) { + $counter['assign'] = $params['assign']; + } + + if (isset($counter['assign'])) { + $smarty->assign($counter['assign'], $counter['count']); + } + + if (isset($params['print'])) { + $print = (bool)$params['print']; + } else { + $print = empty($counter['assign']); + } + + if ($print) { + $retval = $counter['count']; + } else { + $retval = null; + } + + if (isset($params['skip'])) { + $counter['skip'] = $params['skip']; + } + + if (isset($params['direction'])) { + $counter['direction'] = $params['direction']; + } + + if ($counter['direction'] == "down") + $counter['count'] -= $counter['skip']; + else + $counter['count'] += $counter['skip']; + + return $retval; + +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.cycle.php b/Tools/projectGenerator/smarty/plugins/function.cycle.php new file mode 100644 index 000000000..fe78bb87d --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.cycle.php @@ -0,0 +1,102 @@ + + * Name: cycle
+ * Date: May 3, 2002
+ * Purpose: cycle through given values
+ * Input: + * - name = name of cycle (optional) + * - values = comma separated list of values to cycle, + * or an array of values to cycle + * (this can be left out for subsequent calls) + * - reset = boolean - resets given var to true + * - print = boolean - print var or not. default is true + * - advance = boolean - whether or not to advance the cycle + * - delimiter = the value delimiter, default is "," + * - assign = boolean, assigns to template var instead of + * printed. + * + * Examples:
+ *
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * 
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle} + * (Smarty online manual) + * @author Monte Ohrt + * @author credit to Mark Priatel + * @author credit to Gerard + * @author credit to Jason Sweat + * @version 1.3 + * @param array + * @param Smarty + * @return string|null + */ +function smarty_function_cycle($params, &$smarty) +{ + static $cycle_vars; + + $name = (empty($params['name'])) ? 'default' : $params['name']; + $print = (isset($params['print'])) ? (bool)$params['print'] : true; + $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true; + $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false; + + if (!in_array('values', array_keys($params))) { + if(!isset($cycle_vars[$name]['values'])) { + $smarty->trigger_error("cycle: missing 'values' parameter"); + return; + } + } else { + if(isset($cycle_vars[$name]['values']) + && $cycle_vars[$name]['values'] != $params['values'] ) { + $cycle_vars[$name]['index'] = 0; + } + $cycle_vars[$name]['values'] = $params['values']; + } + + $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ','; + + if(is_array($cycle_vars[$name]['values'])) { + $cycle_array = $cycle_vars[$name]['values']; + } else { + $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']); + } + + if(!isset($cycle_vars[$name]['index']) || $reset ) { + $cycle_vars[$name]['index'] = 0; + } + + if (isset($params['assign'])) { + $print = false; + $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]); + } + + if($print) { + $retval = $cycle_array[$cycle_vars[$name]['index']]; + } else { + $retval = null; + } + + if($advance) { + if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) { + $cycle_vars[$name]['index'] = 0; + } else { + $cycle_vars[$name]['index']++; + } + } + + return $retval; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.debug.php b/Tools/projectGenerator/smarty/plugins/function.debug.php new file mode 100644 index 000000000..43452307b --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.debug.php @@ -0,0 +1,35 @@ + + * Name: debug
+ * Date: July 1, 2002
+ * Purpose: popup debug window + * @link http://smarty.php.net/manual/en/language.function.debug.php {debug} + * (Smarty online manual) + * @author Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string output from {@link Smarty::_generate_debug_output()} + */ +function smarty_function_debug($params, &$smarty) +{ + if (isset($params['output'])) { + $smarty->assign('_smarty_debug_output', $params['output']); + } + require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); + return smarty_core_display_debug_console(null, $smarty); +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.eval.php b/Tools/projectGenerator/smarty/plugins/function.eval.php new file mode 100644 index 000000000..ff0472de2 --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.eval.php @@ -0,0 +1,49 @@ + + * Name: eval
+ * Purpose: evaluate a template variable as a template
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval} + * (Smarty online manual) + * @author Monte Ohrt + * @param array + * @param Smarty + */ +function smarty_function_eval($params, &$smarty) +{ + + if (!isset($params['var'])) { + $smarty->trigger_error("eval: missing 'var' parameter"); + return; + } + + if($params['var'] == '') { + return; + } + + $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled); + + ob_start(); + $smarty->_eval('?>' . $_var_compiled); + $_contents = ob_get_contents(); + ob_end_clean(); + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'], $_contents); + } else { + return $_contents; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.fetch.php b/Tools/projectGenerator/smarty/plugins/function.fetch.php new file mode 100644 index 000000000..81b1bfc6b --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.fetch.php @@ -0,0 +1,221 @@ + + * Name: fetch
+ * Purpose: fetch file, web or ftp data and display results + * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch} + * (Smarty online manual) + * @author Monte Ohrt + * @param array + * @param Smarty + * @return string|null if the assign parameter is passed, Smarty assigns the + * result to a template variable + */ +function smarty_function_fetch($params, &$smarty) +{ + if (empty($params['file'])) { + $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty"); + return; + } + + $content = ''; + if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) { + $_params = array('resource_type' => 'file', 'resource_name' => $params['file']); + require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); + if(!smarty_core_is_secure($_params, $smarty)) { + $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed'); + return; + } + + // fetch the file + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\''); + return; + } + } else { + // not a local file + if(preg_match('!^http://!i',$params['file'])) { + // http fetch + if($uri_parts = parse_url($params['file'])) { + // set defaults + $host = $server_name = $uri_parts['host']; + $timeout = 30; + $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"; + $agent = "Smarty Template Engine ".$smarty->_version; + $referer = ""; + $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/'; + $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : ''; + $_is_proxy = false; + if(empty($uri_parts['port'])) { + $port = 80; + } else { + $port = $uri_parts['port']; + } + if(!empty($uri_parts['user'])) { + $user = $uri_parts['user']; + } + if(!empty($uri_parts['pass'])) { + $pass = $uri_parts['pass']; + } + // loop through parameters, setup headers + foreach($params as $param_key => $param_value) { + switch($param_key) { + case "file": + case "assign": + case "assign_headers": + break; + case "user": + if(!empty($param_value)) { + $user = $param_value; + } + break; + case "pass": + if(!empty($param_value)) { + $pass = $param_value; + } + break; + case "accept": + if(!empty($param_value)) { + $accept = $param_value; + } + break; + case "header": + if(!empty($param_value)) { + if(!preg_match('![\w\d-]+: .+!',$param_value)) { + $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'"); + return; + } else { + $extra_headers[] = $param_value; + } + } + break; + case "proxy_host": + if(!empty($param_value)) { + $proxy_host = $param_value; + } + break; + case "proxy_port": + if(!preg_match('!\D!', $param_value)) { + $proxy_port = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + case "agent": + if(!empty($param_value)) { + $agent = $param_value; + } + break; + case "referer": + if(!empty($param_value)) { + $referer = $param_value; + } + break; + case "timeout": + if(!preg_match('!\D!', $param_value)) { + $timeout = (int) $param_value; + } else { + $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'"); + return; + } + break; + default: + $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'"); + return; + } + } + if(!empty($proxy_host) && !empty($proxy_port)) { + $_is_proxy = true; + $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout); + } else { + $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout); + } + + if(!$fp) { + $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)"); + return; + } else { + if($_is_proxy) { + fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n"); + } else { + fputs($fp, "GET $uri HTTP/1.0\r\n"); + } + if(!empty($host)) { + fputs($fp, "Host: $host\r\n"); + } + if(!empty($accept)) { + fputs($fp, "Accept: $accept\r\n"); + } + if(!empty($agent)) { + fputs($fp, "User-Agent: $agent\r\n"); + } + if(!empty($referer)) { + fputs($fp, "Referer: $referer\r\n"); + } + if(isset($extra_headers) && is_array($extra_headers)) { + foreach($extra_headers as $curr_header) { + fputs($fp, $curr_header."\r\n"); + } + } + if(!empty($user) && !empty($pass)) { + fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n"); + } + + fputs($fp, "\r\n"); + while(!feof($fp)) { + $content .= fgets($fp,4096); + } + fclose($fp); + $csplit = split("\r\n\r\n",$content,2); + + $content = $csplit[1]; + + if(!empty($params['assign_headers'])) { + $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0])); + } + } + } else { + $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax"); + return; + } + } else { + // ftp fetch + if($fp = @fopen($params['file'],'r')) { + while(!feof($fp)) { + $content .= fgets ($fp,4096); + } + fclose($fp); + } else { + $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\''); + return; + } + } + + } + + + if (!empty($params['assign'])) { + $smarty->assign($params['assign'],$content); + } else { + return $content; + } +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.html_checkboxes.php b/Tools/projectGenerator/smarty/plugins/function.html_checkboxes.php new file mode 100644 index 000000000..ed8ad7f33 --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.html_checkboxes.php @@ -0,0 +1,143 @@ + + * Type: function
+ * Name: html_checkboxes
+ * Date: 24.Feb.2003
+ * Purpose: Prints out a list of checkbox input types
+ * Input:
+ * - name (optional) - string default "checkbox" + * - values (required) - array + * - options (optional) - associative array + * - checked (optional) - array default not set + * - separator (optional) - ie
or   + * - output (optional) - the output next to each checkbox + * - assign (optional) - assign the output as an array to this variable + * Examples: + *
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='
' output=$names} + * {html_checkboxes values=$ids checked=$checked separator='
' output=$names} + *
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes} + * (Smarty online manual) + * @author Christopher Kvarme + * @author credits to Monte Ohrt + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_checkboxes($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $name = 'checkbox'; + $values = null; + $options = null; + $selected = null; + $separator = ''; + $labels = true; + $output = null; + + $extra = ''; + + foreach($params as $_key => $_val) { + switch($_key) { + case 'name': + case 'separator': + $$_key = $_val; + break; + + case 'labels': + $$_key = (bool)$_val; + break; + + case 'options': + $$_key = (array)$_val; + break; + + case 'values': + case 'output': + $$_key = array_values((array)$_val); + break; + + case 'checked': + case 'selected': + $selected = array_map('strval', array_values((array)$_val)); + break; + + case 'checkboxes': + $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING); + $options = (array)$_val; + break; + + case 'assign': + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (!isset($options) && !isset($values)) + return ''; /* raise error here? */ + + settype($selected, 'array'); + $_html_result = array(); + + if (isset($options)) { + + foreach ($options as $_key=>$_val) + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + + + } else { + foreach ($values as $_i=>$_key) { + $_val = isset($output[$_i]) ? $output[$_i] : ''; + $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels); + } + + } + + if(!empty($params['assign'])) { + $smarty->assign($params['assign'], $_html_result); + } else { + return implode("\n",$_html_result); + } + +} + +function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) { + $_output = ''; + if ($labels) $_output .= ''; + $_output .= $separator; + + return $_output; +} + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.html_image.php b/Tools/projectGenerator/smarty/plugins/function.html_image.php new file mode 100644 index 000000000..9abae72ef --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.html_image.php @@ -0,0 +1,142 @@ + + * Name: html_image
+ * Date: Feb 24, 2003
+ * Purpose: format HTML tags for the image
+ * Input:
+ * - file = file (and path) of image (required) + * - height = image height (optional, default actual height) + * - width = image width (optional, default actual width) + * - basedir = base directory for absolute paths, default + * is environment variable DOCUMENT_ROOT + * - path_prefix = prefix for path output (optional, default empty) + * + * Examples: {html_image file="/images/masthead.gif"} + * Output: + * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image} + * (Smarty online manual) + * @author Monte Ohrt + * @author credits to Duda - wrote first image function + * in repository, helped with lots of functionality + * @version 1.0 + * @param array + * @param Smarty + * @return string + * @uses smarty_function_escape_special_chars() + */ +function smarty_function_html_image($params, &$smarty) +{ + require_once $smarty->_get_plugin_filepath('shared','escape_special_chars'); + + $alt = ''; + $file = ''; + $height = ''; + $width = ''; + $extra = ''; + $prefix = ''; + $suffix = ''; + $path_prefix = ''; + $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; + $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : ''; + foreach($params as $_key => $_val) { + switch($_key) { + case 'file': + case 'height': + case 'width': + case 'dpi': + case 'path_prefix': + case 'basedir': + $$_key = $_val; + break; + + case 'alt': + if(!is_array($_val)) { + $$_key = smarty_function_escape_special_chars($_val); + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + + case 'link': + case 'href': + $prefix = ''; + $suffix = ''; + break; + + default: + if(!is_array($_val)) { + $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"'; + } else { + $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE); + } + break; + } + } + + if (empty($file)) { + $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE); + return; + } + + if (substr($file,0,1) == '/') { + $_image_path = $basedir . $file; + } else { + $_image_path = $file; + } + + if(!isset($params['width']) || !isset($params['height'])) { + if(!$_image_data = @getimagesize($_image_path)) { + if(!file_exists($_image_path)) { + $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE); + return; + } else if(!is_readable($_image_path)) { + $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE); + return; + } else { + $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE); + return; + } + } + if ($smarty->security && + ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) && + (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) && + (!smarty_core_is_secure($_params, $smarty)) ) { + $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE); + } + + if(!isset($params['width'])) { + $width = $_image_data[0]; + } + if(!isset($params['height'])) { + $height = $_image_data[1]; + } + + } + + if(isset($params['dpi'])) { + if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) { + $dpi_default = 72; + } else { + $dpi_default = 96; + } + $_resize = $dpi_default/$params['dpi']; + $width = round($width * $_resize); + $height = round($height * $_resize); + } + + return $prefix . ''.$alt.'' . $suffix; +} + +/* vim: set expandtab: */ + +?> diff --git a/Tools/projectGenerator/smarty/plugins/function.html_options.php b/Tools/projectGenerator/smarty/plugins/function.html_options.php new file mode 100644 index 000000000..cebadde47 --- /dev/null +++ b/Tools/projectGenerator/smarty/plugins/function.html_options.php @@ -0,0 +1,122 @@ + + * Name: html_options
+ * Input:
+ * - name (optional) - string default "select" + * - values (required if no options supplied) - array + * - options (required if no values supplied) - associative array + * - selected (optional) - string default not set + * - output (required if not options supplied) - array + * Purpose: Prints the list of