Browse Source

Update file dialog check.

Jérémie Dumas 6 years ago
parent
commit
473edba1d7
2 changed files with 72 additions and 27 deletions
  1. 37 15
      include/igl/file_dialog_open.cpp
  2. 35 12
      include/igl/file_dialog_save.cpp

+ 37 - 15
include/igl/file_dialog_open.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "file_dialog_open.h"
 #include "file_dialog_open.h"
 #include <cstdio>
 #include <cstdio>
@@ -13,7 +13,7 @@
   #include <windows.h>
   #include <windows.h>
   #undef max
   #undef max
   #undef min
   #undef min
-  
+
   #include <Commdlg.h>
   #include <Commdlg.h>
 #endif
 #endif
 
 
@@ -22,7 +22,8 @@ IGL_INLINE std::string igl::file_dialog_open()
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   char buffer[FILE_DIALOG_MAX_BUFFER];
   char buffer[FILE_DIALOG_MAX_BUFFER];
   buffer[0] = '\0';
   buffer[0] = '\0';
-  
+  buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0'
+
 #ifdef __APPLE__
 #ifdef __APPLE__
   // For apple use applescript hack
   // For apple use applescript hack
   FILE * output = popen(
   FILE * output = popen(
@@ -33,12 +34,22 @@ IGL_INLINE std::string igl::file_dialog_open()
     "   end tell\n"
     "   end tell\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "\" 2>/dev/null | tr -d '\n' ","r");
     "\" 2>/dev/null | tr -d '\n' ","r");
-  if( !output || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) == NULL || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL || ferror(output))
+  if (output)
   {
   {
-    buffer[0] = '\0';
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
   }
 #elif defined _WIN32
 #elif defined _WIN32
-  
+
   // Use native windows file dialog box
   // Use native windows file dialog box
   // (code contributed by Tino Weinkauf)
   // (code contributed by Tino Weinkauf)
 
 
@@ -50,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_open()
   ofn.lStructSize = sizeof(ofn);
   ofn.lStructSize = sizeof(ofn);
   ofn.hwndOwner = NULL;
   ofn.hwndOwner = NULL;
   ofn.lpstrFile = new char[100];
   ofn.lpstrFile = new char[100];
-  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
+  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
   // use the contents of szFile to initialize itself.
   // use the contents of szFile to initialize itself.
   ofn.lpstrFile[0] = '\0';
   ofn.lpstrFile[0] = '\0';
   ofn.nMaxFile = sizeof(szFile);
   ofn.nMaxFile = sizeof(szFile);
@@ -61,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_open()
   ofn.lpstrInitialDir = NULL;
   ofn.lpstrInitialDir = NULL;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 
 
-  // Display the Open dialog box. 
+  // Display the Open dialog box.
   int pos = 0;
   int pos = 0;
   if (GetOpenFileName(&ofn)==TRUE)
   if (GetOpenFileName(&ofn)==TRUE)
   {
   {
@@ -70,17 +81,28 @@ IGL_INLINE std::string igl::file_dialog_open()
       buffer[pos] = (char)ofn.lpstrFile[pos];
       buffer[pos] = (char)ofn.lpstrFile[pos];
       pos++;
       pos++;
     }
     }
-  } 
+  }
   buffer[pos] = 0;
   buffer[pos] = 0;
 #else
 #else
-  
+
   // For linux use zenity
   // For linux use zenity
   FILE * output = popen("/usr/bin/zenity --file-selection","r");
   FILE * output = popen("/usr/bin/zenity --file-selection","r");
-  if( !output || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) == NULL || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL || ferror(output))
+  if (output)
   {
   {
-    buffer[0] = '\0';
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
   }
 
 
+  // Replace last '\n' by '\0'
   if(strlen(buffer) > 0)
   if(strlen(buffer) > 0)
   {
   {
     buffer[strlen(buffer)-1] = '\0';
     buffer[strlen(buffer)-1] = '\0';

+ 35 - 12
include/igl/file_dialog_save.cpp

@@ -1,9 +1,9 @@
 // This file is part of libigl, a simple c++ geometry processing library.
 // This file is part of libigl, a simple c++ geometry processing library.
-// 
+//
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
 // Copyright (C) 2014 Daniele Panozzo <[email protected]>
-// 
-// This Source Code Form is subject to the terms of the Mozilla Public License 
-// v. 2.0. If a copy of the MPL was not distributed with this file, You can 
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
 // obtain one at http://mozilla.org/MPL/2.0/.
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "file_dialog_save.h"
 #include "file_dialog_save.h"
 #include <cstdio>
 #include <cstdio>
@@ -19,6 +19,8 @@ IGL_INLINE std::string igl::file_dialog_save()
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   const int FILE_DIALOG_MAX_BUFFER = 1024;
   char buffer[FILE_DIALOG_MAX_BUFFER];
   char buffer[FILE_DIALOG_MAX_BUFFER];
   buffer[0] = '\0';
   buffer[0] = '\0';
+  buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0'
+
 #ifdef __APPLE__
 #ifdef __APPLE__
   // For apple use applescript hack
   // For apple use applescript hack
   // There is currently a bug in Applescript that strips extensions off
   // There is currently a bug in Applescript that strips extensions off
@@ -32,9 +34,19 @@ IGL_INLINE std::string igl::file_dialog_save()
     "   end tell\n"
     "   end tell\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "   set existing_file_path to (POSIX path of (existing_file))\n"
     "\" 2>/dev/null | tr -d '\n' ","r");
     "\" 2>/dev/null | tr -d '\n' ","r");
-  if( !output || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) == NULL || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL || ferror(output))
+  if (output)
   {
   {
-    buffer[0] = '\0';
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
   }
 #elif defined _WIN32
 #elif defined _WIN32
 
 
@@ -49,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_save()
   ofn.lStructSize = sizeof(ofn);
   ofn.lStructSize = sizeof(ofn);
   ofn.hwndOwner = NULL;//hwnd;
   ofn.hwndOwner = NULL;//hwnd;
   ofn.lpstrFile = new char[100];
   ofn.lpstrFile = new char[100];
-  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
+  // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
   // use the contents of szFile to initialize itself.
   // use the contents of szFile to initialize itself.
   ofn.lpstrFile[0] = '\0';
   ofn.lpstrFile[0] = '\0';
   ofn.nMaxFile = sizeof(szFile);
   ofn.nMaxFile = sizeof(szFile);
@@ -60,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_save()
   ofn.lpstrInitialDir = NULL;
   ofn.lpstrInitialDir = NULL;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
 
 
-  // Display the Open dialog box. 
+  // Display the Open dialog box.
   int pos = 0;
   int pos = 0;
   if (GetSaveFileName(&ofn)==TRUE)
   if (GetSaveFileName(&ofn)==TRUE)
   {
   {
@@ -75,16 +87,27 @@ IGL_INLINE std::string igl::file_dialog_save()
 #else
 #else
   // For every other machine type use zenity
   // For every other machine type use zenity
   FILE * output = popen("/usr/bin/zenity --file-selection --save","r");
   FILE * output = popen("/usr/bin/zenity --file-selection --save","r");
-  if( !output || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) == NULL || fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL || ferror(output))
+  if (output)
   {
   {
-    buffer[0] = '\0';
+    auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output);
+    if (ret == NULL || ferror(output))
+    {
+      // I/O error
+      buffer[0] = '\0';
+    }
+    if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0')
+    {
+      // File name too long, buffer has been filled, so we return empty string instead
+      buffer[0] = '\0';
+    }
   }
   }
-  
+
+  // Replace last '\n' by '\0'
   if(strlen(buffer) > 0)
   if(strlen(buffer) > 0)
   {
   {
     buffer[strlen(buffer)-1] = '\0';
     buffer[strlen(buffer)-1] = '\0';
   }
   }
-  
+
 #endif
 #endif
   return std::string(buffer);
   return std::string(buffer);
 }
 }