@@ -69,6 +69,29 @@ static void InsertUnique(std::vector<gd::String> &container, gd::String str) {
69
69
container.push_back (str);
70
70
}
71
71
72
+ static gd::String CleanProjectName (gd::String projectName) {
73
+ gd::String partiallyCleanedProjectName = projectName;
74
+
75
+ static const gd::String forbiddenFileNameCharacters =
76
+ " \\ /:*?\" <>|" ; // See
77
+ // https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file
78
+
79
+ for (size_t i = 0 ; i < partiallyCleanedProjectName.size ();) {
80
+ // Delete all characters that are not allowed in a filename
81
+ if (forbiddenFileNameCharacters.find (partiallyCleanedProjectName[i]) !=
82
+ gd::String::npos) {
83
+ partiallyCleanedProjectName.erase (i, 1 );
84
+ } else {
85
+ i++;
86
+ }
87
+ }
88
+
89
+ if (partiallyCleanedProjectName.empty ())
90
+ partiallyCleanedProjectName = " Project" ;
91
+
92
+ return partiallyCleanedProjectName;
93
+ }
94
+
72
95
ExporterHelper::ExporterHelper (gd::AbstractFileSystem &fileSystem,
73
96
gd::String gdjsRoot_,
74
97
gd::String codeOutputDir_)
@@ -101,8 +124,9 @@ bool ExporterHelper::ExportProjectForPixiPreview(
101
124
} else {
102
125
// Most of the time, we skip the logo and minimum duration so that
103
126
// the preview start as soon as possible.
104
- exportedProject.GetLoadingScreen ().ShowGDevelopLogoDuringLoadingScreen (false ).SetMinDuration (
105
- 0 );
127
+ exportedProject.GetLoadingScreen ()
128
+ .ShowGDevelopLogoDuringLoadingScreen (false )
129
+ .SetMinDuration (0 );
106
130
exportedProject.GetWatermark ().ShowGDevelopWatermark (false );
107
131
}
108
132
@@ -308,16 +332,22 @@ bool ExporterHelper::ExportCordovaFiles(const gd::Project &project,
308
332
}
309
333
310
334
// Splashscreen icon for Android 12+.
311
- gd::String splashScreenIconFilename = getIconFilename (" android" , " windowSplashScreenAnimatedIcon" );
335
+ gd::String splashScreenIconFilename =
336
+ getIconFilename (" android" , " windowSplashScreenAnimatedIcon" );
312
337
if (!splashScreenIconFilename.empty ())
313
- output += " <preference name=\" AndroidWindowSplashScreenAnimatedIcon\" value=\" "
314
- + splashScreenIconFilename + " \" />\n " ;
338
+ output +=
339
+ " <preference name=\" AndroidWindowSplashScreenAnimatedIcon\" "
340
+ " value=\" " +
341
+ splashScreenIconFilename + " \" />\n " ;
315
342
316
343
// Splashscreen "branding" image for Android 12+.
317
- gd::String splashScreenBrandingImageFilename = getIconFilename (" android" , " windowSplashScreenBrandingImage" );
344
+ gd::String splashScreenBrandingImageFilename =
345
+ getIconFilename (" android" , " windowSplashScreenBrandingImage" );
318
346
if (!splashScreenBrandingImageFilename.empty ())
319
- output += " <preference name=\" AndroidWindowSplashScreenBrandingImage\" value=\" "
320
- + splashScreenBrandingImageFilename + " \" />\n " ;
347
+ output +=
348
+ " <preference name=\" AndroidWindowSplashScreenBrandingImage\" "
349
+ " value=\" " +
350
+ splashScreenBrandingImageFilename + " \" />\n " ;
321
351
322
352
return output;
323
353
};
@@ -458,11 +488,15 @@ bool ExporterHelper::ExportElectronFiles(const gd::Project &project,
458
488
->GetMangledSceneName (project.GetName ())
459
489
.LowerCase ()
460
490
.FindAndReplace (" " , " -" )));
491
+ // It's important to clean the project name from special characters,
492
+ // otherwise Windows executable may be corrupted when electron builds it.
493
+ gd::String jsonCleanedName = gd::Serializer::ToJSON (
494
+ gd::SerializerElement (CleanProjectName (project.GetName ())));
461
495
462
496
{
463
497
gd::String str =
464
498
fs.ReadFile (gdjsRoot + " /Runtime/Electron/package.json" )
465
- .FindAndReplace (" \" GDJS_GAME_NAME\" " , jsonName )
499
+ .FindAndReplace (" \" GDJS_GAME_NAME\" " , jsonCleanedName )
466
500
.FindAndReplace (" \" GDJS_GAME_PACKAGE_NAME\" " , jsonPackageName)
467
501
.FindAndReplace (" \" GDJS_GAME_AUTHOR\" " , jsonAuthor)
468
502
.FindAndReplace (" \" GDJS_GAME_VERSION\" " , jsonVersion)
@@ -651,10 +685,8 @@ void ExporterHelper::AddLibsInclude(bool pixiRenderers,
651
685
InsertUnique (includesFiles, " pixi-renderers/pixi-bitmapfont-manager.js" );
652
686
InsertUnique (includesFiles,
653
687
" pixi-renderers/spriteruntimeobject-pixi-renderer.js" );
654
- InsertUnique (includesFiles,
655
- " pixi-renderers/CustomObjectPixiRenderer.js" );
656
- InsertUnique (includesFiles,
657
- " pixi-renderers/DebuggerPixiRenderer.js" );
688
+ InsertUnique (includesFiles, " pixi-renderers/CustomObjectPixiRenderer.js" );
689
+ InsertUnique (includesFiles, " pixi-renderers/DebuggerPixiRenderer.js" );
658
690
InsertUnique (includesFiles,
659
691
" pixi-renderers/loadingscreen-pixi-renderer.js" );
660
692
InsertUnique (includesFiles, " pixi-renderers/pixi-effects-manager.js" );
0 commit comments