2 Utilities for VFS modules.
4 Copyright (C) 1988-2019
5 Free Software Foundation, Inc.
7 Copyright (C) 1995, 1996 Miguel de Icaza
9 This file is part of the Midnight Commander.
11 The Midnight Commander is free software: you can redistribute it
12 and/or modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation, either version 3 of the License,
14 or (at your option) any later version.
16 The Midnight Commander is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * \brief Source: Utilities for VFS modules
28 * \author Miguel de Icaza
35 #include <sys/types.h>
41 #include "lib/global.h"
42 #include "lib/unixcompat.h"
43 #include "lib/util.h" /* mc_mkstemps() */
44 #include "lib/widget.h" /* message() */
45 #include "lib/strutil.h" /* INVALID_CONV */
50 /*** global variables ****************************************************************************/
52 /*** file scope macro definitions ****************************************************************/
61 #define MC_HISTORY_VFS_PASSWORD "mc.vfs.password"
64 * FIXME2, the "-993" is to reduce the chance of a hit on the first lookup.
66 #define GUID_DEFAULT_CONST -993
68 /*** file scope type declarations ****************************************************************/
70 /*** file scope variables ************************************************************************/
72 /*** file scope functions ************************************************************************/
73 /* --------------------------------------------------------------------------------------------- */
76 /* --------------------------------------------------------------------------------------------- */
77 /*** public functions ****************************************************************************/
78 /* --------------------------------------------------------------------------------------------- */
79 /** Get current username
81 * @return g_malloc()ed string with the name of the currently logged in
82 * user ("anonymous" if uid is not registered in the system)
86 vfs_get_local_username (void)
90 p_i
= getpwuid (geteuid ());
92 return (p_i
&& p_i
->pw_name
) ? g_strdup (p_i
->pw_name
) : g_strdup ("anonymous"); /* Unknown UID, strange */
95 /* --------------------------------------------------------------------------------------------- */
97 * Look up a user or group name from a uid/gid, maintaining a cache.
98 * FIXME, for now it's a one-entry cache.
99 * This file should be modified for non-unix systems to do something
103 /* --------------------------------------------------------------------------------------------- */
106 vfs_finduid (const char *uname
)
108 static int saveuid
= GUID_DEFAULT_CONST
;
109 static char saveuname
[TUNMLEN
] = "\0";
111 if (uname
[0] != saveuname
[0] /* Quick test w/o proc call */
112 || 0 != strncmp (uname
, saveuname
, TUNMLEN
))
116 g_strlcpy (saveuname
, uname
, TUNMLEN
);
117 pw
= getpwnam (uname
);
120 saveuid
= pw
->pw_uid
;
124 static int my_uid
= GUID_DEFAULT_CONST
;
135 /* --------------------------------------------------------------------------------------------- */
138 vfs_findgid (const char *gname
)
140 static int savegid
= GUID_DEFAULT_CONST
;
141 static char savegname
[TGNMLEN
] = "\0";
144 if (gname
[0] != savegname
[0] /* Quick test w/o proc call */
145 || 0 != strncmp (gname
, savegname
, TUNMLEN
))
149 g_strlcpy (savegname
, gname
, TUNMLEN
);
150 gr
= getgrnam (gname
);
153 savegid
= gr
->gr_gid
;
157 static int my_gid
= GUID_DEFAULT_CONST
;
168 /* --------------------------------------------------------------------------------------------- */
170 * Create a temporary file with a name resembling the original.
171 * This is needed e.g. for local copies requested by extfs.
172 * Some extfs scripts may look at the extension.
173 * We also protect stupid scripts agains dangerous names.
177 vfs_mkstemps (vfs_path_t
** pname_vpath
, const char *prefix
, const char *param_basename
)
184 /* Strip directories */
185 p
= strrchr (param_basename
, PATH_SEP
);
191 /* Protection against very long names */
192 shift
= strlen (p
) - (MC_MAXPATHLEN
- 16);
196 suffix
= g_string_sized_new (32);
198 /* Protection against unusual characters */
199 for (; *p
!= '\0' && *p
!= '#'; p
++)
200 if (strchr (".-_@", *p
) != NULL
|| g_ascii_isalnum (*p
))
201 g_string_append_c (suffix
, *p
);
203 fd
= mc_mkstemps (pname_vpath
, prefix
, suffix
->str
);
204 g_string_free (suffix
, TRUE
);
209 /* --------------------------------------------------------------------------------------------- */
210 /** Extract the hostname and username from the path
212 * Format of the path is [user@]hostname:port/remote-dir, e.g.:
214 * ftp://sunsite.unc.edu/pub/linux
215 * ftp://miguel@sphinx.nuclecu.unam.mx/c/nc
216 * ftp://tsx-11.mit.edu:8192/
217 * ftp://joe@foo.edu:11321/private
218 * ftp://joe:password@foo.se
220 * @param path is an input string to be parsed
221 * @param default_port is an input default port
222 * @param flags are parsing modifier flags (@see vfs_url_flags_t)
224 * @return g_malloc()ed url info.
225 * If the user is empty, e.g. ftp://@roxanne/private, and URL_USE_ANONYMOUS
226 * is not set, then the current login name is supplied.
227 * Return value is a g_malloc()ed structure with the pathname relative to the
232 vfs_url_split (const char *path
, int default_port
, vfs_url_flags_t flags
)
234 vfs_path_element_t
*path_element
;
239 char *colon
, *at
, *rest
;
241 path_element
= g_new0 (vfs_path_element_t
, 1);
242 path_element
->port
= default_port
;
244 pcopy_len
= strlen (path
);
245 pcopy
= g_strndup (path
, pcopy_len
);
246 pend
= pcopy
+ pcopy_len
;
248 if ((flags
& URL_NOSLASH
) == 0)
252 /* locate path component */
253 while (!IS_PATH_SEP (*dir
) && *dir
!= '\0')
256 path_element
->path
= g_strdup (PATH_SEP_STR
);
259 path_element
->path
= g_strndup (dir
, pcopy_len
- (size_t) (dir
- pcopy
));
264 /* search for any possible user */
265 at
= strrchr (pcopy
, '@');
267 /* We have a username */
275 inner_colon
= strchr (pcopy
, ':');
276 if (inner_colon
!= NULL
)
280 path_element
->password
= g_strdup (inner_colon
);
284 path_element
->user
= g_strdup (pcopy
);
292 if ((flags
& URL_USE_ANONYMOUS
) == 0)
294 g_free (path_element
->user
);
295 path_element
->user
= vfs_get_local_username ();
297 /* Check if the host comes with a port spec, if so, chop it */
299 colon
= strchr (rest
, ':');
302 colon
= strchr (++rest
, ']');
311 vfs_path_element_free (path_element
);
320 /* cppcheck-suppress invalidscanf */
321 if (sscanf (colon
+ 1, "%d", &path_element
->port
) == 1)
323 if (path_element
->port
<= 0 || path_element
->port
>= 65536)
324 path_element
->port
= default_port
;
327 while (*(++colon
) != '\0')
332 path_element
->port
= 1;
335 path_element
->port
= 2;
343 path_element
->host
= g_strdup (rest
);
346 path_element
->dir
.converter
= INVALID_CONV
;
352 /* --------------------------------------------------------------------------------------------- */
354 void __attribute__ ((noreturn
)) vfs_die (const char *m
)
356 message (D_ERROR
, _("Internal error:"), "%s", m
);
360 /* --------------------------------------------------------------------------------------------- */
363 vfs_get_password (const char *msg
)
365 return input_dialog (msg
, _("Password:"), MC_HISTORY_VFS_PASSWORD
, INPUT_PASSWORD
,
366 INPUT_COMPLETE_NONE
);
369 /* --------------------------------------------------------------------------------------------- */