1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999-2021 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #if HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <mailutils/types.h>
26 #include <mailutils/cctype.h>
27 #include <mailutils/util.h>
28 #include <mailutils/mu_auth.h>
29
30 /* NOTE: Allocates Memory. */
31 /* Expand: ~ --> /home/user and to ~guest --> /home/guest. */
32 char *
mu_tilde_expansion(const char * ref,int delim,const char * homedir)33 mu_tilde_expansion (const char *ref, int delim, const char *homedir)
34 {
35 char *base = strdup (ref);
36 char *home = NULL;
37 char *proto = NULL;
38 size_t proto_len = 0;
39 char *p;
40
41 if (!base)
42 return NULL;
43 for (p = base; *p && mu_isascii (*p) && mu_isalnum (*p); p++)
44 ;
45
46 if (*p == ':')
47 {
48 p++;
49 proto_len = p - base;
50 proto = malloc (proto_len + 1);
51 if (!proto)
52 return NULL;
53 memcpy (proto, base, proto_len);
54 proto[proto_len] = 0;
55 /* Allow for extra pair of slashes after the protocol specifier */
56 if (*p == delim)
57 p++;
58 if (*p == delim)
59 p++;
60 }
61 else
62 p = base;
63
64 if (*p == '~')
65 {
66 p++;
67 if (*p == delim || *p == '\0')
68 {
69 char *s;
70 if (!homedir)
71 {
72 home = mu_get_homedir ();
73 if (!home)
74 return base;
75 homedir = home;
76 }
77 s = calloc (proto_len + strlen (homedir) + strlen (p) + 1, 1);
78 if (proto_len)
79 strcpy (s, proto);
80 else
81 s[0] = 0;
82 strcat (s, homedir);
83 strcat (s, p);
84 free (base);
85 base = s;
86 }
87 else
88 {
89 struct mu_auth_data *auth;
90 char *s = p;
91 char *name;
92 while (*s && *s != delim)
93 s++;
94 name = calloc (s - p + 1, 1);
95 memcpy (name, p, s - p);
96 name[s - p] = '\0';
97
98 auth = mu_get_auth_by_name (name);
99 free (name);
100 if (auth)
101 {
102 char *buf = calloc (proto_len + strlen (auth->dir)
103 + strlen (s) + 1, 1);
104 if (proto_len)
105 strcpy (buf, proto);
106 else
107 buf[0] = 0;
108 strcat (buf, auth->dir);
109 strcat (buf, s);
110 free (base);
111 base = buf;
112 mu_auth_data_free (auth);
113 }
114 }
115 }
116 free (proto);
117 free (home);
118 return base;
119 }
120
121