1 /* Mednafen - Multi-system Emulator
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17 
18 #include "mednafen.h"
19 
20 #include <string.h>
21 #include <stdarg.h>
22 
23 #include <sys/types.h>
24 
25 #include <string>
26 
27 #include "general.h"
28 #include "state.h"
29 
30 using namespace std;
31 
IsAbsolutePath(const char * path)32 static bool IsAbsolutePath(const char *path)
33 {
34    if (
35 #ifdef _WIN32
36          path[0] == '\\' ||
37 #endif
38          path[0] == '/'
39       )
40          return(TRUE);
41 
42  #if defined(WIN32) || defined(DOS)
43  if((path[0] >= 'a' && path[0] <= 'z') || (path[0] >= 'A' && path[0] <= 'Z'))
44  {
45     if(path[1] == ':')
46        return(TRUE);
47  }
48  #endif
49 
50  return(FALSE);
51 }
52 
IsAbsolutePath(const std::string & path)53 static bool IsAbsolutePath(const std::string &path)
54 {
55  return(IsAbsolutePath(path.c_str()));
56 }
57 
MDFN_IsFIROPSafe(const std::string & path)58 bool MDFN_IsFIROPSafe(const std::string &path)
59 {
60  // We could make this more OS-specific, but it shouldn't hurt to try to weed out usage of characters that are path
61  // separators in one OS but not in another, and we'd also run more of a risk of missing a special path separator case
62  // in some OS.
63 
64  if(!MDFN_GetSettingB("filesys.untrusted_fip_check"))
65   return(true);
66 
67  if(path.find('\0') != string::npos)
68   return(false);
69 
70  if(path.find(':') != string::npos)
71   return(false);
72 
73  if(path.find('\\') != string::npos)
74   return(false);
75 
76  if(path.find('/') != string::npos)
77   return(false);
78 
79  return(true);
80 }
81 
MDFN_GetFilePathComponents(const std::string & file_path,std::string * dir_path_out,std::string * file_base_out,std::string * file_ext_out)82 void MDFN_GetFilePathComponents(const std::string &file_path,
83       std::string *dir_path_out, std::string *file_base_out,
84       std::string *file_ext_out)
85 {
86  size_t final_ds;		                  // in file_path
87  string file_name;
88  size_t fn_final_dot;		            // in local var file_name
89  string dir_path, file_base, file_ext; // Temporary output
90 
91 #ifdef _WIN32
92  final_ds = file_path.find_last_of('\\');
93 
94  size_t alt_final_ds = file_path.find_last_of('/');
95 
96  if(final_ds == string::npos || (alt_final_ds != string::npos && alt_final_ds > final_ds))
97     final_ds = alt_final_ds;
98 #else
99  final_ds = file_path.find_last_of('/');
100 #endif
101 
102  if(final_ds == string::npos)
103  {
104   dir_path = string(".");
105   file_name = file_path;
106  }
107  else
108  {
109   dir_path = file_path.substr(0, final_ds);
110   file_name = file_path.substr(final_ds + 1);
111  }
112 
113  fn_final_dot = file_name.find_last_of('.');
114 
115  if(fn_final_dot != string::npos)
116  {
117   file_base = file_name.substr(0, fn_final_dot);
118   file_ext = file_name.substr(fn_final_dot);
119  }
120  else
121  {
122   file_base = file_name;
123   file_ext = string("");
124  }
125 
126  if(dir_path_out)
127   *dir_path_out = dir_path;
128 
129  if(file_base_out)
130   *file_base_out = file_base;
131 
132  if(file_ext_out)
133   *file_ext_out = file_ext;
134 }
135 
MDFN_EvalFIP(const std::string & dir_path,const std::string & rel_path,bool skip_safety_check)136 std::string MDFN_EvalFIP(const std::string &dir_path, const std::string &rel_path, bool skip_safety_check)
137 {
138    char slash;
139 #ifdef _WIN32
140    slash = '\\';
141 #else
142    slash = '/';
143 #endif
144 
145    if(!skip_safety_check && !MDFN_IsFIROPSafe(rel_path))
146       throw MDFN_Error(0, _("Referenced path \"%s\" is potentially unsafe.  See \"filesys.untrusted_fip_check\" setting.\n"), rel_path.c_str());
147 
148    if(IsAbsolutePath(rel_path.c_str()))
149       return(rel_path);
150    else
151       return(dir_path + slash + rel_path);
152 }
153 
GetFNComponent(const char * str)154 const char * GetFNComponent(const char *str)
155 {
156    const char *tp1;
157 
158 #ifdef _WIN32
159    tp1 = ((char *)strrchr(str,'\\'));
160 
161    const char *tp3;
162 
163    tp3 = ((char *)strrchr(str,'/'));
164 
165    if (tp1<tp3)
166       tp1 = tp3;
167 #else
168    tp1 = ((char *)strrchr(str,'/'));
169 #endif
170 
171    if (tp1)
172       return (tp1+1);
173    else
174       return (str);
175 }
176