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