Hi !

Using PHYSFS_getDirSeparator() instead of "/" breaks warzone under
windows. I already did changes to fix this problem.

Best regards,

Rod.



Per Inge Mathisen wrote:
> This is a beginning of an audit of the paths code. I'm not entirely
> sure if this is the best way of doing it, though. Please take a quick
> look.
> 
> What should we do about hardcoded paths in the source? I would suggest
> leaving them as in the data files, using windoze '\' separators), but
> not using "\\" double notation, and using unix_path() everywhere to
> convert to system specific path separators. And rename unix_path() and
> make it convert to PHYSFS_getDirSeparator() separator instead of '/'.
> 
>   - Per
> 
> 
> ------------------------------------------------------------------------
> 
> Index: lib/framework/frame.h
> ===================================================================
> --- lib/framework/frame.h     (revision 15)
> +++ lib/framework/frame.h     (working copy)
> @@ -157,4 +157,6 @@
>  UINT HashString( char *String );
>  UINT HashStringIgnoreCase( char *String );
>  
> +void PHYSFS_dircat(char *path, size_t size, const char *subdir);
> +
>  #endif
> Index: lib/framework/frameresource.c
> ===================================================================
> --- lib/framework/frameresource.c     (revision 15)
> +++ lib/framework/frameresource.c     (working copy)
> @@ -433,7 +433,7 @@
>                       return FALSE;
>               }
>               strcpy(aFileName, aCurrResDir);
> -             strcat(aFileName, pFile);
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), pFile);
>  
>               strcpy(LastResourceFilename,pFile);     // Save the filename in 
> case any routines need it
>               resToLower(LastResourceFilename);
> Index: lib/framework/frame_stub.c
> ===================================================================
> --- lib/framework/frame_stub.c        (revision 15)
> +++ lib/framework/frame_stub.c        (working copy)
> @@ -485,6 +485,22 @@
>  }
>  
>  /***************************************************************************
> +     Append a directory to a path in a platform-independent way.
> +***************************************************************************/
> +void PHYSFS_dircat(char *path, size_t size, const char *subdir)
> +{
> +     const char *separator = PHYSFS_getDirSeparator();
> +  const char *separators = "/\\:";
> +
> +     if (strlen(path) == 0 || strchr(separators, path[strlen(path) - 1])) {
> +             strncat(path, subdir, size);
> +     } else {
> +             strncat(path, separator, size);
> +             strncat(path, subdir, size);
> +     }
> +}
> +
> +/***************************************************************************
>    Load the file with name pointed to by pFileName into a memory buffer. 
>    If AllocateMem is true then the memory is allocated ... else it is 
>    already in allocated in ppFileData, and the max size is in pFileSize 
> @@ -600,9 +616,8 @@
>               debug(LOG_ERROR, "saveFile: PHYSFS_getRealDir(%s) returns 
> NULL?!",
>                     filename);
>       } else {
> -       debug(LOG_WZ, "Successfully wrote to %s%s%s with %d bytes", 
> -                   PHYSFS_getRealDir(filename), PHYSFS_getDirSeparator(), 
> -                   filename, size);
> +       debug(LOG_WZ, "Successfully wrote to %s in %s with %d bytes", 
> +                   filename, PHYSFS_getRealDir(filename), size);
>       }
>       return TRUE;
>  }
> Index: src/multigifts.c
> ===================================================================
> --- src/multigifts.c  (revision 15)
> +++ src/multigifts.c  (working copy)
> @@ -1065,8 +1065,9 @@
>               setPower(selectedPlayer,LEV_HI);                // reset power.
>               sendPowerCheck(TRUE);                                   // tell 
> everyone.
>  
> -             strcpy(sTemp, "multiplay\\Forces\\");                   
> -             strcat(sTemp, sForceName);      
> +             strcpy(sTemp, "multiplay");
> +             PHYSFS_dircat(sTemp, sizeof(sTemp), "forces");
> +             PHYSFS_dircat(sTemp, sizeof(sTemp), sForceName);
>               strcat(sTemp,".For");   
>               loadForce( sTemp);
>       
> Index: src/revision.h
> ===================================================================
> --- src/revision.h    (revision 15)
> +++ src/revision.h    (working copy)
> @@ -1 +1 @@
> -#define SVN_REVISION "Revision ????"
> +#define SVN_REVISION "Revision 15M"
> Index: src/clparse.c
> ===================================================================
> --- src/clparse.c     (revision 15)
> +++ src/clparse.c     (working copy)
> @@ -143,8 +143,7 @@
>                               return FALSE;
>                       }
>                       strcpy(saveGameName, SaveGamePath);
> -                     strcat(saveGameName, "/");
> -                     strncat(saveGameName, token, 240);
> +                     PHYSFS_dircat(saveGameName, sizeof(saveGameName), 
> token);
>                       SetGameMode(GS_SAVEGAMELOAD);
>               }
>               else if( stricmp( tokenType,cl2) == 0)
> Index: src/game.c
> ===================================================================
> --- src/game.c        (revision 15)
> +++ src/game.c        (working copy)
> @@ -1352,7 +1352,6 @@
>       strcpy(aFileName, pGameToLoad);
>       fileExten = strlen(pGameToLoad) - 3;
>       aFileName[fileExten - 1] = '\0';
> -     strcat(aFileName, "\\");
>  
>  #ifdef SAVE_PROXIMITY
>       if (saveGameVersion >= VERSION_11)
> @@ -1365,7 +1364,7 @@
>               {
>                       //load in the proximity list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "proxState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "proxState.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -1394,7 +1393,7 @@
>               {
>                       //load in the message list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "mesState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "mesState.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -1766,7 +1765,6 @@
>       strcpy(aFileName, pGameToLoad);
>       fileExten = strlen(aFileName) - 3;                      // hack - !
>       aFileName[fileExten - 1] = '\0';
> -     strcat(aFileName, "\\");
>  
>       //the terrain type WILL only change with Campaign changes (well at the 
> moment!)
>       //if (freeMem) - this now works for Cam Start and Cam Change
> @@ -1776,7 +1774,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the terrain type map
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "TTypes.ttp");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "TTypes.ttp");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -1840,7 +1838,7 @@
>  //load in the templates
>               LOADBARCALLBACK();      //      loadingScreenCallback();
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "templ.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "templ.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -1876,7 +1874,7 @@
>  //           aMapLinePoints = NULL;
>               //load in the map file 
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "mission.map");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mission.map");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -1890,7 +1888,7 @@
>    
>               //load in the visibility file 
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "misvis.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "misvis.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -1918,7 +1916,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the features -do before the structures
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "mFeat.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mFeat.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -1936,7 +1934,7 @@
>  
>               //load in the mission structures
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "mStruct.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mStruct.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -1969,11 +1967,11 @@
>  
>               if (saveGameVersion < VERSION_27)//V27
>               {
> -                     strcat(aFileName, "mDroid.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "mDroid.bjo");
>               }
>               else
>               {
> -                     strcat(aFileName, "mUnit.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "mUnit.bjo");
>               }
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
> @@ -2011,7 +2009,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the flag list file
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "mFlagState.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mFlagState.bjo");
>               // Load in the chosen file data 
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2052,7 +2050,7 @@
>               aMapLinePoints = NULL;
>               //load in the map file 
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "game.map");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "game.map");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2072,7 +2070,7 @@
>  #ifdef JOHN
>               // load in the gateway map
>  /*           aFileName[fileExten] = '\0';
> -             strcat(aFileName, "gates.txt");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "gates.txt");
>               // Load in the chosen file data
>  #ifndef PSX
>               pFileData = DisplayBuffer;
> @@ -2120,7 +2118,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the research list file
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "resState.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "resState.bjo");
>               // Load in the chosen file data 
>  //#ifndef PSX
>               pFileData = DisplayBuffer;
> @@ -2149,7 +2147,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the droid initialisation file
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "dinit.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "dinit.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2172,11 +2170,11 @@
>               aFileName[fileExten] = '\0';
>               if (saveGameVersion < VERSION_27)//V27
>               {
> -                     strcat(aFileName, "droid.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "droid.bjo");
>               }
>               else
>               {
> -                     strcat(aFileName, "unit.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), "unit.bjo");
>               }
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
> @@ -2223,11 +2221,11 @@
>                               aFileName[fileExten] = '\0';
>                               if (saveGameVersion < VERSION_27)//V27
>                               {
> -                                     strcat(aFileName, "mDroid.bjo");
> +                                     PHYSFS_dircat(aFileName, 
> sizeof(aFileName), "mDroid.bjo");
>                               }
>                               else
>                               {
> -                                     strcat(aFileName, "mUnit.bjo");
> +                                     PHYSFS_dircat(aFileName, 
> sizeof(aFileName), "mUnit.bjo");
>                               }
>                               /* Load in the chosen file data */
>                               pFileData = DisplayBuffer;
> @@ -2252,7 +2250,7 @@
>       {
>               //load in the limbo droids
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "limbo.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "limbo.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2271,7 +2269,7 @@
>       LOADBARCALLBACK();      //      loadingScreenCallback();
>       //load in the features -do before the structures
>       aFileName[fileExten] = '\0';
> -     strcat(aFileName, "feat.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "feat.bjo");
>       /* Load in the chosen file data */
>       pFileData = DisplayBuffer;
>       if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2293,7 +2291,7 @@
>  //load in the structures
>       LOADBARCALLBACK();      //      loadingScreenCallback();
>       aFileName[fileExten] = '\0';
> -     strcat(aFileName, "struct.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "struct.bjo");
>       /* Load in the chosen file data */
>       pFileData = DisplayBuffer;
>       if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2326,7 +2324,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the component list file
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "compL.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "compL.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2348,7 +2346,7 @@
>               LOADBARCALLBACK();      //              loadingScreenCallback();
>               //load in the structure type list file
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "strType.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "strType.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2380,7 +2378,7 @@
>               {
>                       //load in the visibility file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "VisState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "VisState.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2411,7 +2409,7 @@
>               {
>                       //load in the message list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "prodState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "prodState.bjo");
>                       // Load in the chosen file data 
>               pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2440,7 +2438,7 @@
>               {
>                       //load in the message list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "FXState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "FXState.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2470,7 +2468,7 @@
>               {
>                       //load in the message list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "Score.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "Score.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (loadFileToBufferNoError(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2502,7 +2500,7 @@
>               {
>                       //load in the flag list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "flagState.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "flagState.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (!loadFileToBuffer(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2534,7 +2532,7 @@
>               {
>                       //load in the command list file
>                       aFileName[fileExten] = '\0';
> -                     strcat(aFileName, "command.bjo");
> +                     PHYSFS_dircat(aFileName, sizeof(aFileName), 
> "command.bjo");
>                       // Load in the chosen file data 
>                       pFileData = DisplayBuffer;
>                       if (!loadFileToBuffer(aFileName, pFileData, 
> displayBufferSize, &fileSize))
> @@ -2562,7 +2560,7 @@
>       {
>               //load in the mission structures
>               aFileName[fileExten] = '\0';
> -             strcat(aFileName, "limits.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "limits.bjo");
>               /* Load in the chosen file data */
>               pFileData = DisplayBuffer;
>               if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -2835,8 +2833,7 @@
>       (void) PHYSFS_mkdir(aFileName);
>  
>       //save the map file
> -     strcat(aFileName, "/");
> -     strcat(aFileName, "game.map");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "game.map");
>       /* Write the data to the file */
>       if (!writeMapFile(aFileName))
>       {
> @@ -2845,7 +2842,7 @@
>  
>       //create the droids filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "unit.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "unit.bjo");
>       /*Write the current droid lists to the file*/
>       //ppsCurrentDroidLists = apsDroidLists;
>       if (!writeDroidFile(aFileName,apsDroidLists))
> @@ -2855,7 +2852,7 @@
>  
>       //create the structures filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "struct.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "struct.bjo");
>       /*Write the data to the file*/
>       if (!writeStructFile(aFileName))
>       {
> @@ -2865,7 +2862,7 @@
>      //we do this later on!!!!
>       //create the production filename
>       // aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "prod.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "prod.bjo");
>       //Write the data to the file
>       if (!writeProductionFile(aFileName))
>       {
> @@ -2875,7 +2872,7 @@
>  
>       //create the templates filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "templ.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "templ.bjo");
>       /*Write the data to the file*/
>       if (!writeTemplateFile(aFileName))
>       {
> @@ -2884,7 +2881,7 @@
>  
>       //create the features filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "feat.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "feat.bjo");
>       /*Write the data to the file*/
>       if (!writeFeatureFile(aFileName))
>       {
> @@ -2893,7 +2890,7 @@
>  
>       //create the terrain types filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "TTypes.ttp");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "TTypes.ttp");
>       /*Write the data to the file*/
>       if (!writeTerrainTypeMapFile(aFileName))
>       {
> @@ -2902,7 +2899,7 @@
>  
>       //create the strucutLimits filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "limits.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "limits.bjo");
>       /*Write the data to the file*/
>       if (!writeStructLimitsFile(aFileName))
>       {
> @@ -2911,7 +2908,7 @@
>  
>       //create the component lists filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "CompL.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "CompL.bjo");
>       /*Write the data to the file*/
>       if (!writeCompListFile(aFileName))
>       {
> @@ -2919,7 +2916,7 @@
>       }
>       //create the structure type lists filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "StrType.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "StrType.bjo");
>       /*Write the data to the file*/
>       if (!writeStructTypeListFile(aFileName))
>       {
> @@ -2928,7 +2925,7 @@
>       
>       //create the research filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "ResState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "ResState.bjo");
>       /*Write the data to the file*/
>       if (!writeResearchFile(aFileName))
>       {
> @@ -2938,7 +2935,7 @@
>  //#ifdef NEW_SAVE //V11 Save 
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "MesState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "MesState.bjo");
>       /*Write the data to the file*/
>       if (!writeMessageFile(aFileName))
>       {
> @@ -2949,7 +2946,7 @@
>  //#ifdef NEW_SAVE //V14 Save 
>       //create the proximity message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "ProxState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "ProxState.bjo");
>       /*Write the data to the file*/
>       if (!writeMessageFile(aFileName))
>       {
> @@ -2960,7 +2957,7 @@
>  //#ifdef NEW_SAVE //V11 Save 
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "VisState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "VisState.bjo");
>       /*Write the data to the file*/
>       if (!writeVisibilityData(aFileName))
>       {
> @@ -2971,7 +2968,7 @@
>  //#ifdef NEW_SAVE_V13 //V13 Save     
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "ProdState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "ProdState.bjo");
>       /*Write the data to the file*/
>       if (!writeProductionFile(aFileName))
>       {
> @@ -2983,7 +2980,7 @@
>  //#ifdef FX_SAVE //added at V13 save 
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "FXState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "FXState.bjo");
>       /*Write the data to the file*/
>       if (!writeFXData(aFileName))
>       {
> @@ -2994,7 +2991,7 @@
>       //added at V15 save     
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "Score.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "Score.bjo");
>       /*Write the data to the file*/
>       if (!writeScoreData(aFileName))
>       {
> @@ -3005,7 +3002,7 @@
>  //#ifdef NEW_SAVE //V12 Save 
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "FlagState.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "FlagState.bjo");
>       /*Write the data to the file*/
>       if (!writeFlagFile(aFileName))
>       {
> @@ -3016,7 +3013,7 @@
>  //#ifdef NEW_SAVE //V21 Save 
>       //create the message filename
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "command.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "command.bjo");
>       /*Write the data to the file*/
>       if (!writeCommandLists(aFileName))
>       {
> @@ -3026,7 +3023,7 @@
>  
>       //create the structLimits filename
>       /*aFileName[sOFN.nFileExtension] = '\0';
> -     strcat(aFileName, "limits.bjo");*/
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "limits.bjo");*/
>       /*Write the data to the file DONE IN SCRIPTS NOW*/
>       /*if (!writeStructLimitsFile(aFileName))
>       {
> @@ -3047,7 +3044,7 @@
>  
>       //create the droids filename
>       aFileName[fileExtension-1] = '\0';
> -     strcat(aFileName, "\\mUnit.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "mUnit.bjo");
>       /*Write the swapped droid lists to the file*/
>       //ppsCurrentDroidLists = mission.apsDroidLists;
>       if (!writeDroidFile(aFileName, mission.apsDroidLists))
> @@ -3074,7 +3071,7 @@
>       }
>  
>       aFileName[fileExtension] = '\0';
> -     strcat(aFileName, "limbo.bjo");
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "limbo.bjo");
>       /*Write the swapped droid lists to the file*/
>       //ppsCurrentDroidLists = apsLimboDroids;
>       if (!writeDroidFile(aFileName, apsLimboDroids))
> @@ -3091,7 +3088,7 @@
>               
>               //save the map file
>               aFileName[fileExtension] = '\0';
> -             strcat(aFileName, "mission.map");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mission.map");
>               /* Write the data to the file */
>               if (!writeMapFile(aFileName))
>               {
> @@ -3100,7 +3097,7 @@
>  
>               //save the map file
>               aFileName[fileExtension] = '\0';
> -             strcat(aFileName, "misvis.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "misvis.bjo");
>               /* Write the data to the file */
>               if (!writeVisibilityData(aFileName))
>               {
> @@ -3109,7 +3106,7 @@
>  
>               //create the structures filename
>               aFileName[fileExtension] = '\0';
> -             strcat(aFileName, "mStruct.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mStruct.bjo");
>               /*Write the data to the file*/
>               if (!writeStructFile(aFileName))
>               {
> @@ -3118,7 +3115,7 @@
>  
>               //create the features filename
>               aFileName[fileExtension] = '\0';
> -             strcat(aFileName, "mFeat.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mFeat.bjo");
>               /*Write the data to the file*/
>               if (!writeFeatureFile(aFileName))
>               {
> @@ -3127,7 +3124,7 @@
>  
>               //create the message filename
>               aFileName[fileExtension] = '\0';
> -             strcat(aFileName, "mFlagState.bjo");
> +             PHYSFS_dircat(aFileName, sizeof(aFileName), "mFlagState.bjo");
>               /*Write the data to the file*/
>               if (!writeFlagFile(aFileName))
>               {
> @@ -10643,7 +10640,7 @@
>       levFindDataSet(game.map, &psLevel);
>       strcpy(aFileName,psLevel->apDataFiles[0]);
>       aFileName[strlen(aFileName)-4] = '\0';
> -     strcat(aFileName, "\\struct.bjo");              
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "struct.bjo");              
>  
>       pFileData = DisplayBuffer;
>       if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -10773,7 +10770,7 @@
>       levFindDataSet(game.map, &psLevel);
>       strcpy(aFileName,psLevel->apDataFiles[0]);
>       aFileName[strlen(aFileName)-4] = '\0';
> -     strcat(aFileName, "\\struct.bjo");              
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "struct.bjo");              
>  
>       pFileData = DisplayBuffer;
>       if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> Index: src/multiplay.c
> ===================================================================
> --- src/multiplay.c   (revision 15)
> +++ src/multiplay.c   (working copy)
> @@ -1424,45 +1424,30 @@
>  // Network File packet processor.
>  BOOL recvMapFileRequested(NETMSG *pMsg)
>  {
> -     char mapStr[256],mapName[256],fixedname[256];
> +     char mapName[256], fixedname[256], *sptr = game.map;
>  
> -//   pMsg;
> -
>       // another player is requesting the map
> -     if(!NetPlay.bHost)
> -     {
> +     if (!NetPlay.bHost) {
>               return TRUE;
>       }
>  
> -//#ifndef DISABLEMAPSEND
>       // start sending the map to the other players.
> -     if(!bSendingMap)
> -     {
> -             memset(mapStr,0,256);
> +     if (!bSendingMap) {
>               memset(mapName,0,256);
>               memset(fixedname,0,256);
>               bSendingMap = TRUE;
>               addConsoleMessage("SENDING MAP!",DEFAULT_JUSTIFY);
> -             addConsoleMessage("FIX FOR LINUX!",DEFAULT_JUSTIFY);
>  
> -             strcpy(mapName,game.map);
> -             // chop off the -T1
> -             mapName[strlen(game.map)-3] = 0;                // chop off the 
> -T1 etc..
> -
> -             // chop off the sk- if required.
> -             if(strncmp(mapName,"Sk-",3) == 0)
> -             {
> -                     strcpy(mapStr,&(mapName[3]));
> -                     strcpy(mapName,mapStr);
> +             if (strncmp(game.map, "Sk-", 3) == 0) {
> +                     sptr += 3;              // chop off the sk- if required
>               }
> -
> -             sprintf(mapStr,"%dc-%s",game.maxPlayers,mapName);
> -             strcat(mapStr,".wz");//.wdg
> -             sprintf(fixedname,"maps\\%s",mapStr);           //We know maps 
> are in /maps dir...now. fix for linux -Q
> -             memcpy(mapStr,fixedname,256);
> -             NETsendFile(TRUE,mapStr,0);
> +             sprintf(mapName, "%dc-%s", game.maxPlayers, sptr);
> +             mapName[strlen(mapName) - 3] = '\0';            // chop off the 
> -T1/-T2/-T3
> +             strcat(mapName, ".wz");
> +             strcpy(fixedname, "maps");
> +             PHYSFS_dircat(fixedname, sizeof(fixedname), mapName);
> +             NETsendFile(TRUE, fixedname, 0);
>       }
> -//#endif
>       return TRUE;
>  }
>  
> Index: src/multiopt.c
> ===================================================================
> --- src/multiopt.c    (revision 15)
> +++ src/multiopt.c    (working copy)
> @@ -635,7 +635,7 @@
>       if(game.type == CAMPAIGN && game.base == CAMP_WALLS)
>       {
>               strcpy(sTemp, MultiForcesPath);                 
> -             strcat(sTemp, sForceName);      
> +             PHYSFS_dircat(sTemp, sizeof(sTemp), sForceName);        
>               strcat(sTemp,".For");   
>       
>               loadForce(sTemp);
> @@ -886,8 +886,9 @@
>               setPower(i,LEV_HI);                                             
>         // set deathmatch power to hi.
>       }
>  
> -     strcpy(sTemp, "multiplay\\Forces\\");                   
> -     strcat(sTemp, sForceName);      
> +     strcpy(sTemp, "multiplay");
> +     PHYSFS_dircat(sTemp, sizeof(sTemp), "forces");
> +     PHYSFS_dircat(sTemp, sizeof(sTemp), sForceName);
>       strcat(sTemp,".For");   
>       loadForce( sTemp);
>  
> Index: src/multiint.c
> ===================================================================
> --- src/multiint.c    (revision 15)
> +++ src/multiint.c    (working copy)
> @@ -212,7 +212,7 @@
>       levFindDataSet(game.map, &psLevel);
>       strcpy(aFileName,psLevel->apDataFiles[0]);
>       aFileName[strlen(aFileName)-4] = '\0';
> -     strcat(aFileName, "\\game.map");                
> +     PHYSFS_dircat(aFileName, sizeof(aFileName), "game.map");                
>  
>       pFileData = DisplayBuffer;
>       if (!loadFileToBuffer(aFileName, pFileData, displayBufferSize, 
> &fileSize))
> @@ -486,7 +486,7 @@
>  
>       // try and load it from the maps directory first,
>       strcpy(pLevelName, MultiCustomMapsPath);                        
> -     strcat(pLevelName, game.map);
> +     PHYSFS_dircat(pLevelName, sizeof(pLevelName), game.map);
>       strcat(pLevelName, ".wrf");     
>       debug(LOG_WZ, "decideWRF: %s", pLevelName);     
>       //if the file exists in the downloaded maps dir then use that one 
> instead.
> @@ -1954,7 +1954,7 @@
>                       widgDelete(psWScreen,FRONTEND_SIDETEXT2);               
>                         // del text too,
>  
>                       strcpy(tmp,MultiCustomMapsPath);
> -                     strcat(tmp,"*.wrf");
> +                     PHYSFS_dircat(tmp, sizeof(tmp), "*.wrf");
>                       debug(LOG_WZ, "processMultiopWidgets[MULTIOP_MAP_ICON]: 
> %s", tmp);
>                       addMultiRequest(tmp,MULTIOP_MAP,1);
>                       break;
> @@ -2248,7 +2248,7 @@
>               widgDelete(psWScreen,MULTIOP_PLAYERS);
>               widgDelete(psWScreen,FRONTEND_SIDETEXT2);                       
>                 // del text too,
>               strcpy(tmp,MultiForcesPath);
> -             strcat(tmp,"*.for");
> +             PHYSFS_dircat(tmp, sizeof(tmp), "*.for");
>               addMultiRequest(tmp,MULTIOP_FNAME,0);
>               break;
>       
> @@ -2281,7 +2281,7 @@
>               widgDelete(psWScreen,FRONTEND_SIDETEXT2);                       
>                 // del text too,
>  
>               strcpy(tmp,MultiPlayersPath);
> -             strcat(tmp,"*.sta");
> +             PHYSFS_dircat(tmp, sizeof(tmp), "*.sta");
>               addMultiRequest(tmp,MULTIOP_PNAME,0);
>               break;
>  
> @@ -3227,7 +3227,9 @@
>                       break;
>  
>               case FORCE_PRESETDEFAULT:       
> -                     strcpy(dir,"multiplay\\Forces\\Default.FOR");
> +                     strcpy(dir, "multiplay");
> +                     PHYSFS_dircat(dir, sizeof(dir), "forces");
> +                     PHYSFS_dircat(dir, sizeof(dir), "default.for");
>                       loadForce(dir);                         
>                       AvailableForces();                                      
>                                         // update force screen
>                       CurrentForce();
> @@ -3274,7 +3276,9 @@
>       selectedPlayer = FORCEEDITPLAYER;
>       setPower(selectedPlayer,FORCEEDIT_POWER);
>  
> -     strcpy(dir,"multiplay\\Forces\\default.FOR");           // start with 
> default force.
> +     strcpy(dir, "multiplay");
> +     PHYSFS_dircat(dir, sizeof(dir), "forces");
> +     PHYSFS_dircat(dir, sizeof(dir), "default.for");
>       if(!loadForce(dir))
>       {
>               DBPRINTF(("Error Loading Force"));
> Index: src/multimenu.c
> ===================================================================
> --- src/multimenu.c   (revision 15)
> +++ src/multimenu.c   (working copy)
> @@ -591,7 +591,7 @@
>       }
>  
>       strcpy(tmp,MultiCustomMapsPath);
> -     strcat(tmp,"*.wrf");
> +     PHYSFS_dircat(tmp, sizeof(tmp), "*.wrf");
>       if( id == M_REQUEST_C1)
>       {
>               closeMultiRequester();
> Index: src/main.c
> ===================================================================
> --- src/main.c        (revision 15)
> +++ src/main.c        (working copy)
> @@ -53,16 +53,16 @@
>  BOOL reInit = FALSE;
>  BOOL bDisableLobby;
>  BOOL pQUEUE=TRUE;                    //This is used to control our pQueue 
> list. Always ON except for SP games! -Q
> -char SaveGamePath[255];
> -char ScreenDumpPath[255];
> -char MultiForcesPath[255];
> -char MultiCustomMapsPath[255];
> -char MultiPlayersPath[255];
> -char KeyMapPath[255];
> +char SaveGamePath[MAX_PATH];
> +char ScreenDumpPath[MAX_PATH];
> +char MultiForcesPath[MAX_PATH];
> +char MultiCustomMapsPath[MAX_PATH];
> +char MultiPlayersPath[MAX_PATH];
> +char KeyMapPath[MAX_PATH];
>  char*        UserMusicPath;
>  char default_data_path[MAX_PATH];
> -char __UserMusicPath[255];
> -char RegFilePath[255];
> +char __UserMusicPath[MAX_PATH];
> +char RegFilePath[MAX_PATH];
>  
>  /*
>  BOOL checkDisableLobby(void)
> @@ -119,7 +119,7 @@
>                     writepath, PHYSFS_getLastError());
>               exit(1);
>    }
> -     strcat(writepath, writedir);
> +     PHYSFS_dircat(writepath, sizeof(writepath), writedir);
>    (void) PHYSFS_mkdir(writedir); /* Just in case it does not exist yet */
>    if (PHYSFS_setWriteDir(writepath) == 0) {
>               debug(LOG_ERROR, "Error setting write directory to \"%s\": %s",
> @@ -130,8 +130,7 @@
>  
>       if (*default_data_path != '\0') {
>               strcpy(datapath, default_data_path);
> -             strcat(datapath, "/");
> -             strcat(datapath, "warzone.wz");
> +             PHYSFS_dircat(datapath, sizeof(datapath), "warzone.wz");
>               if (!PHYSFS_addToSearchPath(datapath, 1)) {
>                       debug(LOG_WZ, "Could not find warzone.wz in \"%s\".", 
> default_data_path);
>                       *default_data_path = '\0'; // try current dir instead
> @@ -142,7 +141,7 @@
>               if (!PHYSFS_addToSearchPath(datapath, 1)
>                   || !PHYSFS_exists("gamedesc.lev")) {
>                       debug(LOG_WZ, "%s is not data directory", datapath);
> -                     strcat(datapath, "data");
> +                     PHYSFS_dircat(datapath, sizeof(datapath), "data");
>                       debug(LOG_WZ, "Checking if %s is the data directory", 
> datapath);
>                       if (!PHYSFS_addToSearchPath(datapath, 1)) {
>                               debug(LOG_ERROR, "No game data found anywhere!  
> Aborting...");
> @@ -150,10 +149,10 @@
>                       }
>               }
>       }
> -     snprintf(overridepath, sizeof(overridepath), "%soverride", 
> -              PHYSFS_getBaseDir());
> +  strcpy(overridepath, PHYSFS_getBaseDir());
> +  PHYSFS_dircat(overridepath, sizeof(overridepath), "override");
>       strcpy(mappath, PHYSFS_getBaseDir());
> -     strcat(mappath, "maps");
> +     PHYSFS_dircat(mappath, sizeof(mappath), "maps");
>       if (mod) {
>               snprintf(modpath, sizeof(modpath), "%smods%s%s.wz", 
> PHYSFS_getBaseDir(), 
>                        "/", mod);
> @@ -197,11 +196,11 @@
>  static void make_dir(char *dest, char *dirname, char *subdir)
>  {
>       strcpy(dest, dirname);
> +     (void) PHYSFS_mkdir(dest);
>       if (subdir != NULL) {
> -             strcat(dest, "/");
> -             strcat(dest, subdir);
> +             PHYSFS_dircat(dest, MAX_PATH, subdir);
> +             (void) PHYSFS_mkdir(dest);
>       }
> -     PHYSFS_mkdir(dest);
>       if (PHYSFS_isDirectory(dest) == 0) {
>               debug(LOG_ERROR, "Unable to create directory \"%s\" in write 
> dir \"%s\"!",
>                     dest, PHYSFS_getWriteDir());
> Index: src/seqdisp.c
> ===================================================================
> --- src/seqdisp.c     (revision 15)
> +++ src/seqdisp.c     (working copy)
> @@ -159,7 +159,7 @@
>               {
>                       ASSERT(((strlen(sequenceName) + 
> strlen(aHardPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>                       strcpy(aVideoName,aHardPath);
> -                     strcat(aVideoName,sequenceName);
> +                     PHYSFS_dircat(aVideoName, sizeof(aVideoName), 
> sequenceName);
>               
>                       // check it exists. If not then try CD.
>                       pFileHandle = fopen(aVideoName, "rb");
> @@ -167,7 +167,7 @@
>                       {
>                               ASSERT(((strlen(sequenceName) + 
> strlen(aCDPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>                               strcpy(aVideoName,aCDPath);
> -                             strcat(aVideoName,sequenceName);
> +                             PHYSFS_dircat(aVideoName, sizeof(aVideoName), 
> sequenceName);
>                       }
>                       else
>                       {
> @@ -179,7 +179,7 @@
>               {
>                       ASSERT(((strlen(sequenceName) + 
> strlen(aCDPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>                       strcpy(aVideoName,aCDPath);
> -                     strcat(aVideoName,sequenceName);
> +                     PHYSFS_dircat(aVideoName, sizeof(aVideoName), 
> sequenceName);
>               }
>               else
>               {
> @@ -380,7 +380,8 @@
>                       if (strlen( aCDDrive ) <= (MAX_STR_LENGTH - 20))//leave 
> enough space to add "\\warzone\\sequences\\"
>                       {
>                               strcpy(aCDPath, aCDDrive);
> -                             strcat(aCDPath, "warzone\\sequences\\");
> +                             PHYSFS_dircat(aCDPath, sizeof(aCDPath), 
> "warzone");
> +                             PHYSFS_dircat(aCDPath, sizeof(aCDPath), 
> "sequences");
>                               bCDPath = TRUE;
>                               return;                 //quick fix for vids.
>                       }
> @@ -390,7 +391,8 @@
>  
>       if (!bHardPath)
>       {
> -             strcpy(aHardPath, "sequences\\");
> +    aHardPath[0] = '\0';
> +    PHYSFS_dircat(aHardPath, sizeof(aHardPath), "sequences");
>  /*#ifdef WIN32
>               fileHandle = FindFirstFile("sequences\\*.rpl",&findData);
>               if (fileHandle == INVALID_HANDLE_VALUE)
> @@ -459,7 +461,7 @@
>       {
>               ASSERT(((strlen(videoName) + 
> strlen(aHardPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>               strcpy(aVideoName,aHardPath);
> -             strcat(aVideoName,videoName);
> +             PHYSFS_dircat(aVideoName, sizeof(aVideoName), videoName);
>  
>               // check it exists. If not then try CD.
>               pFileHandle = fopen(aVideoName, "rb");
> @@ -467,7 +469,7 @@
>               {
>                       ASSERT(((strlen(videoName) + 
> strlen(aCDPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>                       strcpy(aVideoName,aCDPath);
> -                     strcat(aVideoName,videoName);
> +                     PHYSFS_dircat(aVideoName, sizeof(aVideoName), 
> videoName);
>               }
>               else if (pFileHandle != NULL)
>               {
> @@ -478,7 +480,7 @@
>       {
>               ASSERT(((strlen(videoName) + 
> strlen(aCDPath))<MAX_STR_LENGTH,"sequence path+name greater than max 
> string"));
>               strcpy(aVideoName,aCDPath);
> -             strcat(aVideoName,videoName);
> +             PHYSFS_dircat(aVideoName, sizeof(aVideoName), videoName);
>       }
>       else
>       {
> @@ -491,8 +493,8 @@
>       if (audioName != NULL)
>       {
>               ASSERT((strlen(audioName)<244,"sequence path+name greater than 
> max string"));
> -             strcpy(aAudioName,"sequenceAudio\\");
> -             strcat(aAudioName,audioName);
> +             strcpy(aAudioName,"sequenceAudio");
> +             PHYSFS_dircat(aAudioName, sizeof(aAudioName), audioName);
>       }
>  
>       //start video mode
> @@ -507,8 +509,8 @@
>       if (audioName != NULL)
>       {
>               ASSERT((strlen(audioName)<244,"sequence path+name greater than 
> max string"));
> -             strcpy(aAudioName,"sequenceAudio\\");
> -             strcat(aAudioName,audioName);
> +             strcpy(aAudioName,"sequenceAudio");
> +             PHYSFS_dircat(aAudioName, sizeof(aAudioName), audioName);
>       }
>  
>  
> @@ -921,8 +923,8 @@
>       SDWORD xOffset, yOffset, startFrame, endFrame;
>       UBYTE* seps     = "\n";
>  
> -     strcpy(aTextName,"sequenceAudio\\");
> -     strcat(aTextName,pTextName);
> +     strcpy(aTextName, "sequenceAudio");
> +     PHYSFS_dircat(aTextName, sizeof(aTextName), pTextName);
>       
>  /*
>       fileHandle = FindFirstFile(aTextName,&findData);
> Index: src/multistat.c
> ===================================================================
> --- src/multistat.c   (revision 15)
> +++ src/multistat.c   (working copy)
> @@ -587,7 +587,7 @@
>       UDWORD                          tmp[4];
>  
>       strcpy(fileName,MultiPlayersPath);
> -     strcat(fileName,sPlayerName);
> +     PHYSFS_dircat(fileName, sizeof(fileName), sPlayerName);
>       strcat(fileName,".sta");
>  
>    debug(LOG_WZ, "loadMultiStats: %s",fileName);      
> @@ -658,7 +658,7 @@
>       NETsetKey(tmp[0],tmp[1],tmp[2],tmp[3]);
>  
>       strcpy(fileName,MultiPlayersPath);
> -     strcat(fileName,sFileName);
> +     PHYSFS_dircat(fileName, sizeof(fileName), sFileName);
>       strcat(fileName,".sta");
>       saveFile(fileName,(UBYTE*)&codedst,sizeof(SAVEDPLAYERSTATS));
>  
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Warzone-dev mailing list
> Warzone-dev@gna.org
> https://mail.gna.org/listinfo/warzone-dev


Reply via email to