~ubuntu-branches/ubuntu/saucy/altermime/saucy

« back to all changes in this revision

Viewing changes to filename-filters.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Valroff
  • Date: 2005-12-30 18:32:54 UTC
  • Revision ID: james.westby@ubuntu.com-20051230183254-vcdpwzgi9g1gooqe
Tags: upstream-0.3.6
ImportĀ upstreamĀ versionĀ 0.3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*------------------------------------------------------------------------
 
2
 Module:        /extra/development/xamime/xamime_working/ripmime/filename-filters.c
 
3
 Author:        Paul L Daniels
 
4
 Project:       ripMIME
 
5
 State:         Release
 
6
 Creation Date: 01 Jan 03
 
7
 Description:   Filename Filters is a module which is designed to check and 'safety-enhance'
 
8
                filenames which are passed to it.  This may include things like removing
 
9
                directory risers ( ../.. ), root directory attempts ( / ), and parameter passing.
 
10
------------------------------------------------------------------------*/
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
#include <string.h>
 
14
#include <errno.h>
 
15
#include <syslog.h>
 
16
#include <ctype.h>
 
17
 
 
18
 
 
19
#include "pldstr.h"
 
20
#include "logger.h"
 
21
#include "filename-filters.h"
 
22
 
 
23
 
 
24
#ifndef FL
 
25
#define FL __FILE__, __LINE__
 
26
#endif
 
27
 
 
28
#define FNFILTER_DEBUG_PEDANTIC 10
 
29
#define FNFILTER_DEBUG_NORMAL 1
 
30
 
 
31
// Debug precodes
 
32
#define FNFILTER_DPEDANTIC ((glb.debug >= FNFILTER_DEBUG_PEDANTIC))
 
33
#define FNFILTER_DNORMAL   ((glb.debug >= FNFILTER_DEBUG_NORMAL  ))
 
34
 
 
35
#define DFN if ((glb.debug >= FNFILTER_DEBUG_NORMAL))
 
36
 
 
37
 
 
38
struct FNFILTER_globals {
 
39
        int debug;
 
40
        int verbose;
 
41
        int paranoid;
 
42
 
 
43
        int x_mac;
 
44
};
 
45
 
 
46
static struct FNFILTER_globals glb;
 
47
 
 
48
 
 
49
int FNFILTER_init( void )
 
50
{
 
51
        glb.debug = 0;
 
52
        glb.verbose = 0;
 
53
        glb.paranoid = 0;
 
54
        glb.x_mac = 0;
 
55
 
 
56
        return 0;
 
57
}
 
58
 
 
59
 
 
60
int FNFILTER_set_debug( int level )
 
61
{
 
62
        glb.debug = level;
 
63
 
 
64
        return glb.debug;
 
65
}
 
66
 
 
67
int FNFILTER_set_verbose( int level )
 
68
{
 
69
        glb.verbose = level;
 
70
 
 
71
        return glb.verbose;
 
72
}
 
73
 
 
74
 
 
75
int FNFILTER_set_mac( int level )
 
76
{
 
77
        glb.x_mac = level;
 
78
 
 
79
        return glb.x_mac;
 
80
}
 
81
 
 
82
int FNFILTER_set_paranoid( int level )
 
83
{
 
84
        glb.paranoid = level;
 
85
 
 
86
        return glb.paranoid;
 
87
}
 
88
 
 
89
 
 
90
/*------------------------------------------------------------------------
 
91
Procedure:     quick_clean_filename ID:1
 
92
Purpose:       Removes non-7bit characers from the filename
 
93
Input:         char *fname: Null terminated string
 
94
Output:
 
95
Errors:
 
96
------------------------------------------------------------------------*/
 
97
int FNFILTER_paranoid_filter( char *fname, int size )
 
98
{
 
99
        char tmp[1024];
 
100
        char *p;
 
101
 
 
102
 
 
103
        /* Scan for . and .. filenames 
 
104
                ** 20040727-12H54
 
105
                ** Patch supplied by Marco Ariano
 
106
                ** Patch modified by Paul L Daniels
 
107
                **
 
108
        */      
 
109
        if ((1 == size)&&('.' == *fname))
 
110
        {
 
111
                *fname = '_';
 
112
                return 0;
 
113
        } else if ((2 == size)&&(0 == strncmp(fname,"..",2))) {
 
114
                snprintf(fname,3,"__");
 
115
                return 0;
 
116
        }
 
117
        
 
118
        
 
119
        /* scan out any directory separators */
 
120
 
 
121
        p = strrchr(fname,'/');
 
122
        if (p)
 
123
        {
 
124
                // Check to see that this seperator isn't the -last- char in the string
 
125
                if (*(p+1) == '\0') *p = '\0';
 
126
                else
 
127
                {
 
128
                        p++;
 
129
                        PLD_strncpy(tmp,p,sizeof(tmp));
 
130
                        PLD_strncpy(fname,tmp,size);
 
131
                }
 
132
        }
 
133
        else if ( (p = strrchr(fname,'\\')))
 
134
        {
 
135
                // Check to see that this seperator isn't the -last- char in the string
 
136
                if (*(p+1) == '\0') *p = '\0';
 
137
                else
 
138
                {
 
139
                        p++;
 
140
                        PLD_strncpy(tmp,p,sizeof(tmp));
 
141
                        PLD_strncpy(fname,tmp,size);
 
142
                }
 
143
        }
 
144
 
 
145
 
 
146
        if ( glb.paranoid > 0 )
 
147
        {
 
148
                // If we're really paranoid, then we go along and convert anything we don't like
 
149
                //      the look of into 7-bit
 
150
                //
 
151
                //      These days we shouldn't be using this any more as there are many filenames
 
152
                //      which require > 7-bit charsets.
 
153
 
 
154
                while (*fname)
 
155
                {
 
156
                        if( !isalnum((int)*fname) && (*fname != '.') ) *fname='_';
 
157
                        if( (*fname < ' ')||(*fname > '~') ) *fname='_';
 
158
                        fname++;
 
159
                }
 
160
        }
 
161
 
 
162
        return 0;
 
163
}
 
164
 
 
165
 
 
166
 
 
167
 
 
168
 
 
169
 
 
170
 
 
171
 
 
172
 
 
173
/*------------------------------------------------------------------------
 
174
Procedure:     MIME_decode_filename ID:1
 
175
Purpose:       Removed spurilous characters from filename strings.
 
176
Input:         char *fname: null terminated character string
 
177
Output:
 
178
Errors:
 
179
------------------------------------------------------------------------*/
 
180
int FNFILTER_filter( char *fname, int size )
 
181
{
 
182
        int fnl;
 
183
        char tmp[1024];
 
184
        char *p;
 
185
 
 
186
        if (fname == NULL) return 0;
 
187
        
 
188
        fnl = strlen(fname);
 
189
 
 
190
        DFN LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: fname[%d chars] = '%s'\n", FL, fnl, fname );
 
191
 
 
192
        /** If we're handling a Mac file, prefilter **/
 
193
        if (glb.x_mac == 1)
 
194
        {
 
195
                char *q = fname;
 
196
 
 
197
                DFN LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: Filtering x-mac filename '%s'",FL,fname);
 
198
                while (*q)
 
199
                {
 
200
                        if (*q == '/') *q = '-'; /** Convert the Mac / separator to a hyphen **/
 
201
                        q++;
 
202
                }
 
203
                DFN LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: x-mac filename is now '%s'",FL,fname);
 
204
        }
 
205
 
 
206
 
 
207
        /* We only look at trimming the quotes off a filename if it has more than 2 chars
 
208
                * because obviously we'll need to strip off 2 chars (leading and finishing quote)
 
209
                */
 
210
        if ( fnl > 2 )
 
211
        {
 
212
 
 
213
                /* if the MIME_filename starts and ends with "'s */
 
214
                if ((fname[0] == '\"') && (fname[fnl-1] == '\"'))
 
215
                {
 
216
                        if (FNFILTER_DNORMAL) LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: Trimming quotes off filename\n", FL );
 
217
 
 
218
                        /* reduce the file namelength by two*/
 
219
                        fnl = fnl -2; // 17-11-2002: was =-2, thanks to Vasily Chernikov for spotting the glaring error!
 
220
 
 
221
                        /* shuffle the MIME_filename chars down */
 
222
                        memmove(fname,fname+1,fnl);
 
223
 
 
224
                        /* terminate the string */
 
225
                        fname[fnl] = '\0';
 
226
                        if (FNFILTER_DNORMAL) LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: Trimming filename done, fname = '%s'\n", FL, fname );
 
227
                } /* if */
 
228
        } /* if */
 
229
 
 
230
        p = strrchr(fname,'/');
 
231
        if (p)
 
232
        {
 
233
                p++;
 
234
                PLD_strncpy( tmp, p, sizeof(tmp) );
 
235
                PLD_strncpy( fname, tmp, size);
 
236
 
 
237
        } else {
 
238
 
 
239
                // Check for Windows/DOS backslash seperator
 
240
 
 
241
                p = strrchr( fname, '\\' );
 
242
                if ( p )
 
243
                {
 
244
                        if ( *(p+1) != '"' )
 
245
                        {
 
246
                                p++;
 
247
                                PLD_strncpy( tmp, p, sizeof(tmp) );
 
248
                                PLD_strncpy( fname, tmp, size );
 
249
                        }
 
250
                }
 
251
        }
 
252
 
 
253
        // Scan for ? symbols - these are often used to make the email client pass paremeters to the filename
 
254
        //      Check though to see that the previous character is not a '=' symbol, because if it is, then we
 
255
        //      actually have an ISO encoded filename
 
256
 
 
257
        p = strchr( fname, '?' );
 
258
        if (p != NULL)
 
259
        {
 
260
                if (p > fname)
 
261
                {
 
262
                        if (*(p-1) != '=')
 
263
                        {
 
264
                                *p = '\0';
 
265
                        } else {
 
266
                                // leave the ? alone, as it's part of an ISO encoded filename
 
267
                        }
 
268
 
 
269
                } else {
 
270
                        // First char of the filename is a '?', change this to a hypen.
 
271
                        *p = '-';
 
272
                }
 
273
        }
 
274
                
 
275
        if (FNFILTER_DNORMAL) LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: Starting paranoia filter\n", FL );
 
276
 
 
277
        FNFILTER_paranoid_filter( fname, strlen( fname ) );
 
278
 
 
279
        if (FNFILTER_DNORMAL) LOGGER_log("%s:%d:FNFILTER_filter:DEBUG: paranoia filter done. Filename='%s'\n", FL, fname );
 
280
 
 
281
        return 0;
 
282
}
 
283
 
 
284
 
 
285
 
 
286
 
 
287