import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / source / smbd / mangle_map.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Name mapping code 
4    Copyright (C) Jeremy Allison 1998
5    Copyright (C) Andrew Tridgell 2002
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24
25 /* ************************************************************************** **
26  * Used only in do_fwd_mangled_map(), below.
27  * ************************************************************************** **
28  */
29 static char *map_filename( char *s,         /* This is null terminated */
30                            const char *pattern,   /* This isn't. */
31                            int len )        /* This is the length of pattern. */
32   {
33   static pstring matching_bit;  /* The bit of the string which matches */
34                                 /* a * in pattern if indeed there is a * */
35   char *sp;                     /* Pointer into s. */
36   char *pp;                     /* Pointer into p. */
37   char *match_start;            /* Where the matching bit starts. */
38   pstring pat;
39
40   StrnCpy( pat, pattern, len ); /* Get pattern into a proper string! */
41   pstrcpy( matching_bit, "" );  /* Match but no star gets this. */
42   pp = pat;                     /* Initialize the pointers. */
43   sp = s;
44
45   if( strequal(s, ".") || strequal(s, ".."))
46     {
47     return NULL;                /* Do not map '.' and '..' */
48     }
49
50   if( (len == 1) && (*pattern == '*') )
51     {
52     return NULL;                /* Impossible, too ambiguous for */
53     }                           /* words! */
54
55   while( (*sp)                  /* Not the end of the string. */
56       && (*pp)                  /* Not the end of the pattern. */
57       && (*sp == *pp)           /* The two match. */
58       && (*pp != '*') )         /* No wildcard. */
59     {
60     sp++;                       /* Keep looking. */
61     pp++;
62     }
63
64   if( !*sp && !*pp )            /* End of pattern. */
65     return( matching_bit );     /* Simple match.  Return empty string. */
66
67   if( *pp == '*' )
68     {
69     pp++;                       /* Always interrested in the chacter */
70                                 /* after the '*' */
71     if( !*pp )                  /* It is at the end of the pattern. */
72       {
73       StrnCpy( matching_bit, s, sp-s );
74       return( matching_bit );
75       }
76     else
77       {
78       /* The next character in pattern must match a character further */
79       /* along s than sp so look for that character. */
80       match_start = sp;
81       while( (*sp)              /* Not the end of s. */
82           && (*sp != *pp) )     /* Not the same  */
83         sp++;                   /* Keep looking. */
84       if( !*sp )                /* Got to the end without a match. */
85         {
86         return( NULL );
87         }                       /* Still hope for a match. */
88       else
89         {
90         /* Now sp should point to a matching character. */
91         StrnCpy(matching_bit, match_start, sp-match_start);
92         /* Back to needing a stright match again. */
93         while( (*sp)            /* Not the end of the string. */
94             && (*pp)            /* Not the end of the pattern. */
95             && (*sp == *pp) )   /* The two match. */
96           {
97           sp++;                 /* Keep looking. */
98           pp++;
99           }
100         if( !*sp && !*pp )      /* Both at end so it matched */
101           return( matching_bit );
102         else
103           return( NULL );
104         }
105       }
106     }
107   return( NULL );               /* No match. */
108   } /* map_filename */
109
110
111 /* ************************************************************************** **
112  * MangledMap is a series of name pairs in () separated by spaces.
113  * If s matches the first of the pair then the name given is the
114  * second of the pair.  A * means any number of any character and if
115  * present in the second of the pair as well as the first the
116  * matching part of the first string takes the place of the * in the
117  * second.
118  *
119  * I wanted this so that we could have RCS files which can be used
120  * by UNIX and DOS programs.  My mapping string is (RCS rcs) which
121  * converts the UNIX RCS file subdirectory to lowercase thus
122  * preventing mangling.
123  *
124  * See 'mangled map' in smb.conf(5).
125  *
126  * ************************************************************************** **
127  */
128 static void mangled_map(char *s, const char *MangledMap)
129 {
130         const char *start=MangledMap;       /* Use this to search for mappings. */
131         const char *end;                    /* Used to find the end of strings. */
132         char *match_string;
133         pstring new_string;           /* Make up the result here. */
134         char *np;                     /* Points into new_string. */
135
136         DEBUG( 5, ("Mangled Mapping '%s' map '%s'\n", s, MangledMap) );
137         while( *start ) {
138                 while( (*start) && (*start != '(') )
139                         start++;
140                 if( !*start )
141                         continue;                 /* Always check for the end. */
142                 start++;                    /* Skip the ( */
143                 end = start;                /* Search for the ' ' or a ')' */
144                 DEBUG( 5, ("Start of first in pair '%s'\n", start) );
145                 while( (*end) && !((*end == ' ') || (*end == ')')) )
146                         end++;
147                 if( !*end ) {
148                         start = end;
149                         continue;                 /* Always check for the end. */
150                 }
151                 DEBUG( 5, ("End of first in pair '%s'\n", end) );
152                 if( (match_string = map_filename( s, start, end-start )) ) {
153                         int size_left = sizeof(new_string) - 1;
154                         DEBUG( 5, ("Found a match\n") );
155                         /* Found a match. */
156                         start = end + 1; /* Point to start of what it is to become. */
157                         DEBUG( 5, ("Start of second in pair '%s'\n", start) );
158                         end = start;
159                         np = new_string;
160                         while( (*end && size_left > 0)    /* Not the end of string. */
161                                && (*end != ')')      /* Not the end of the pattern. */
162                                && (*end != '*') ) {   /* Not a wildcard. */
163                                 *np++ = *end++;
164                                 size_left--;
165                         }
166
167                         if( !*end ) {
168                                 start = end;
169                                 continue;               /* Always check for the end. */
170                         }
171                         if( *end == '*' ) {
172                                 if (size_left > 0 )
173                                         safe_strcpy( np, match_string, size_left );
174                                 np += strlen( match_string );
175                                 size_left -= strlen( match_string );
176                                 end++;                  /* Skip the '*' */
177                                 while ((*end && size_left >  0)   /* Not the end of string. */
178                                        && (*end != ')') /* Not the end of the pattern. */
179                                        && (*end != '*')) { /* Not a wildcard. */
180                                         *np++ = *end++;
181                                         size_left--;
182                                 }
183                         }
184                         if (!*end) {
185                                 start = end;
186                                 continue;               /* Always check for the end. */
187                         }
188                         if (size_left > 0)
189                                 *np++ = '\0';             /* NULL terminate it. */
190                         DEBUG(5,("End of second in pair '%s'\n", end));
191                         new_string[sizeof(new_string)-1] = '\0';
192                         pstrcpy( s, new_string );  /* Substitute with the new name. */
193                         DEBUG( 5, ("s is now '%s'\n", s) );
194                 }
195                 start = end;  /* Skip a bit which cannot be wanted anymore. */
196                 start++;
197         }
198 }
199
200 /*
201   front end routine to the mangled map code 
202   personally I think that the whole idea of "mangled map" is completely bogus
203 */
204 void mangle_map_filename(fstring fname, int snum)
205 {
206         char *map;
207
208         map = lp_mangled_map(snum);
209         if (!map || !*map) return;
210
211         mangled_map(fname, map);
212 }