]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/mangle.c
big merge for db frontend and unicode.
[netatalk.git] / etc / afpd / mangle.c
1 /* 
2  * $Id: mangle.c,v 1.16.2.1.2.1 2003-09-09 16:42:20 didg Exp $ 
3  *
4  * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com)
5  * All Rights Reserved.  See COPYRIGHT.
6  *
7  * mangle, demangle (filename):
8  * mangle or demangle filenames if they are greater than the max allowed
9  * characters for a given version of AFP.
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif /* HAVE_CONFIG_H */
15
16 #include <stdio.h>
17 #include <ctype.h>
18 #include "mangle.h"
19
20 #define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'A' )
21 #define isuxdigit(x)    (isdigit(x) || (isupper(x) && isxdigit(x)))
22
23 char *
24 demangle(const struct vol *vol, char *mfilename) {
25     char *t;
26     char *u_name;
27     u_int32_t id = 0;
28     static char buffer[12 + MAXPATHLEN + 1];
29     int len = 12 + MAXPATHLEN + 1;
30     struct dir  *dir;
31
32
33     t = strchr(mfilename, MANGLE_CHAR);
34     if (t == NULL) {
35             return mfilename;
36         }
37     /* may be a mangled filename */
38     t++;
39     if (*t == '0') { /* can't start with a 0 */
40         return mfilename;
41         }
42     while(isuxdigit(*t)) {
43         id = (id *16) + hextoint(*t);
44         t++;
45     }
46     if ((*t != 0 && *t != '.') || strlen(t) > MAX_EXT_LENGTH || id == 0) {
47             return mfilename;
48         }
49
50     id = htonl(id);
51     /* is it a dir?*/
52     if (NULL != (dir = dirsearch(vol, id))) {
53         return dir->d_u_name;
54         }
55     if (NULL != (u_name = cnid_resolve(vol->v_cdb, &id, buffer, len)) ) {
56         return u_name;
57     }
58     return mfilename;
59 }
60
61 /* -----------------------
62    with utf8 filename not always round trip
63    filename   mac filename too long or with unmatchable utf8 replaced with _
64    uname      unix filename 
65    id         file/folder ID or 0
66    
67 */
68 char *
69 mangle(const struct vol *vol, char *filename, char *uname, cnid_t id, int flags) {
70     char *ext = NULL;
71     char *m = NULL;
72     static char mfilename[MAX_LENGTH + 1];
73     char mangle_suffix[MANGLE_LENGTH + 1];
74     size_t ext_len = 0;
75     int k;
76
77     /* Do we really need to mangle this filename? */
78     if (!flags && strlen(filename) <= vol->max_filename) {
79         return filename;
80     }
81     /* First, attempt to locate a file extension. */
82     if (NULL != (ext = strrchr(uname, '.')) ) {
83         ext_len = strlen(ext);
84         if (ext_len > MAX_EXT_LENGTH) {
85             /* Do some bounds checking to prevent an extension overflow. */
86             ext_len = MAX_EXT_LENGTH;
87         }
88     }
89         m = mfilename;
90     memset(m, 0, MAX_LENGTH + 1);
91     k = sprintf(mangle_suffix, "%c%X", MANGLE_CHAR, ntohl(id));
92
93     strncpy(m, filename, MAX_LENGTH - k - ext_len);
94         strcat(m, mangle_suffix);
95                 strncat(m, ext, ext_len);
96
97     return m;
98 }