s3: Plumb smb_filename through SMB_VFS_STAT and SMB_VFS_LSTAT
[samba.git] / source3 / modules / vfs_cap.c
1 /*
2  * CAP VFS module for Samba 3.x Version 0.3
3  *
4  * Copyright (C) Tim Potter, 1999-2000
5  * Copyright (C) Alexander Bokovoy, 2002-2003
6  * Copyright (C) Stefan (metze) Metzmacher, 2003
7  * Copyright (C) TAKAHASHI Motonobu (monyo), 2003
8  * Copyright (C) Jeremy Allison, 2007
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, see <http://www.gnu.org/licenses/>.
22  */
23
24
25 #include "includes.h"
26
27 /* cap functions */
28 static char *capencode(TALLOC_CTX *ctx, const char *from);
29 static char *capdecode(TALLOC_CTX *ctx, const char *from);
30
31 static uint64_t cap_disk_free(vfs_handle_struct *handle, const char *path,
32         bool small_query, uint64_t *bsize,
33         uint64_t *dfree, uint64_t *dsize)
34 {
35         char *cappath = capencode(talloc_tos(), path);
36
37         if (!cappath) {
38                 errno = ENOMEM;
39                 return (uint64_t)-1;
40         }
41         return SMB_VFS_NEXT_DISK_FREE(handle, cappath, small_query, bsize,
42                                         dfree, dsize);
43 }
44
45 static SMB_STRUCT_DIR *cap_opendir(vfs_handle_struct *handle, const char *fname, const char *mask, uint32 attr)
46 {
47         char *capname = capencode(talloc_tos(), fname);
48
49         if (!capname) {
50                 errno = ENOMEM;
51                 return NULL;
52         }
53         return SMB_VFS_NEXT_OPENDIR(handle, capname, mask, attr);
54 }
55
56 static SMB_STRUCT_DIRENT *cap_readdir(vfs_handle_struct *handle, SMB_STRUCT_DIR *dirp)
57 {
58         SMB_STRUCT_DIRENT *result;
59         SMB_STRUCT_DIRENT *newdirent;
60         char *newname;
61         size_t newnamelen;
62         DEBUG(3,("cap: cap_readdir\n"));
63
64         result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
65         if (!result) {
66                 return NULL;
67         }
68
69         newname = capdecode(talloc_tos(), result->d_name);
70         if (!newname) {
71                 return NULL;
72         }
73         DEBUG(3,("cap: cap_readdir: %s\n", newname));
74         newnamelen = strlen(newname)+1;
75         newdirent = (SMB_STRUCT_DIRENT *)TALLOC_ARRAY(talloc_tos(),
76                         char,
77                         sizeof(SMB_STRUCT_DIRENT)+
78                                 newnamelen);
79         if (!newdirent) {
80                 return NULL;
81         }
82         memcpy(newdirent, result, sizeof(SMB_STRUCT_DIRENT));
83         memcpy(&newdirent->d_name, newname, newnamelen);
84         return newdirent;
85 }
86
87 static int cap_mkdir(vfs_handle_struct *handle, const char *path, mode_t mode)
88 {
89         char *cappath = capencode(talloc_tos(), path);
90
91         if (!cappath) {
92                 errno = ENOMEM;
93                 return -1;
94         }
95         return SMB_VFS_NEXT_MKDIR(handle, cappath, mode);
96 }
97
98 static int cap_rmdir(vfs_handle_struct *handle, const char *path)
99 {
100         char *cappath = capencode(talloc_tos(), path);
101
102         if (!cappath) {
103                 errno = ENOMEM;
104                 return -1;
105         }
106         return SMB_VFS_NEXT_RMDIR(handle, cappath);
107 }
108
109 static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
110                     files_struct *fsp, int flags, mode_t mode)
111 {
112         char *cappath;
113         char *tmp_base_name = NULL;
114         int ret;
115
116         cappath = capencode(talloc_tos(), smb_fname->base_name);
117
118         if (!cappath) {
119                 errno = ENOMEM;
120                 return -1;
121         }
122
123         tmp_base_name = smb_fname->base_name;
124         smb_fname->base_name = cappath;
125
126         DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname)));
127         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
128
129         smb_fname->base_name = tmp_base_name;
130         TALLOC_FREE(cappath);
131
132         return ret;
133 }
134
135 static int cap_rename(vfs_handle_struct *handle, const char *oldname, const char *newname)
136 {
137         char *capold = capencode(talloc_tos(), oldname);
138         char *capnew = capencode(talloc_tos(), newname);
139
140         if (!capold || !capnew) {
141                 errno = ENOMEM;
142                 return -1;
143         }
144         return SMB_VFS_NEXT_RENAME(handle, capold, capnew);
145 }
146
147 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
148 {
149         char *cappath;
150         char *tmp_base_name = NULL;
151         int ret;
152
153         cappath = capencode(talloc_tos(), smb_fname->base_name);
154
155         if (!cappath) {
156                 errno = ENOMEM;
157                 return -1;
158         }
159
160         tmp_base_name = smb_fname->base_name;
161         smb_fname->base_name = cappath;
162
163         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
164
165         smb_fname->base_name = tmp_base_name;
166         TALLOC_FREE(cappath);
167
168         return ret;
169 }
170
171 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
172 {
173         char *cappath;
174         char *tmp_base_name = NULL;
175         int ret;
176
177         cappath = capencode(talloc_tos(), smb_fname->base_name);
178
179         if (!cappath) {
180                 errno = ENOMEM;
181                 return -1;
182         }
183
184         tmp_base_name = smb_fname->base_name;
185         smb_fname->base_name = cappath;
186
187         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
188
189         smb_fname->base_name = tmp_base_name;
190         TALLOC_FREE(cappath);
191
192         return ret;
193 }
194
195 static int cap_unlink(vfs_handle_struct *handle, const char *path)
196 {
197         char *cappath = capencode(talloc_tos(), path);
198
199         if (!cappath) {
200                 errno = ENOMEM;
201                 return -1;
202         }
203         return SMB_VFS_NEXT_UNLINK(handle, cappath);
204 }
205
206 static int cap_chmod(vfs_handle_struct *handle, const char *path, mode_t mode)
207 {
208         char *cappath = capencode(talloc_tos(), path);
209
210         if (!cappath) {
211                 errno = ENOMEM;
212                 return -1;
213         }
214         return SMB_VFS_NEXT_CHMOD(handle, cappath, mode);
215 }
216
217 static int cap_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
218 {
219         char *cappath = capencode(talloc_tos(), path);
220
221         if (!cappath) {
222                 errno = ENOMEM;
223                 return -1;
224         }
225         return SMB_VFS_NEXT_CHOWN(handle, cappath, uid, gid);
226 }
227
228 static int cap_lchown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid)
229 {
230         char *cappath = capencode(talloc_tos(), path);
231
232         if (!cappath) {
233                 errno = ENOMEM;
234                 return -1;
235         }
236         return SMB_VFS_NEXT_LCHOWN(handle, cappath, uid, gid);
237 }
238
239 static int cap_chdir(vfs_handle_struct *handle, const char *path)
240 {
241         char *cappath = capencode(talloc_tos(), path);
242
243         if (!cappath) {
244                 errno = ENOMEM;
245                 return -1;
246         }
247         DEBUG(3,("cap: cap_chdir for %s\n", path));
248         return SMB_VFS_NEXT_CHDIR(handle, cappath);
249 }
250
251 static int cap_ntimes(vfs_handle_struct *handle, const char *path,
252                       struct smb_file_time *ft)
253 {
254         char *cappath = capencode(talloc_tos(), path);
255
256         if (!cappath) {
257                 errno = ENOMEM;
258                 return -1;
259         }
260         return SMB_VFS_NEXT_NTIMES(handle, cappath, ft);
261 }
262
263
264 static bool cap_symlink(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
265 {
266         char *capold = capencode(talloc_tos(), oldpath);
267         char *capnew = capencode(talloc_tos(), newpath);
268
269         if (!capold || !capnew) {
270                 errno = ENOMEM;
271                 return -1;
272         }
273         return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
274 }
275
276 static bool cap_readlink(vfs_handle_struct *handle, const char *path, char *buf, size_t bufsiz)
277 {
278         char *cappath = capencode(talloc_tos(), path);
279
280         if (!cappath) {
281                 errno = ENOMEM;
282                 return -1;
283         }
284         return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
285 }
286
287 static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
288 {
289         char *capold = capencode(talloc_tos(), oldpath);
290         char *capnew = capencode(talloc_tos(), newpath);
291
292         if (!capold || !capnew) {
293                 errno = ENOMEM;
294                 return -1;
295         }
296         return SMB_VFS_NEXT_LINK(handle, capold, capnew);
297 }
298
299 static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
300 {
301         char *cappath = capencode(talloc_tos(), path);
302
303         if (!cappath) {
304                 errno = ENOMEM;
305                 return -1;
306         }
307         return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
308 }
309
310 static char *cap_realpath(vfs_handle_struct *handle, const char *path, char *resolved_path)
311 {
312         /* monyo need capencode'ed and capdecode'ed? */
313         char *cappath = capencode(talloc_tos(), path);
314
315         if (!cappath) {
316                 errno = ENOMEM;
317                 return NULL;
318         }
319         return SMB_VFS_NEXT_REALPATH(handle, path, resolved_path);
320 }
321
322 static int cap_chmod_acl(vfs_handle_struct *handle, const char *path, mode_t mode)
323 {
324         char *cappath = capencode(talloc_tos(), path);
325
326         /* If the underlying VFS doesn't have ACL support... */
327         if (!handle->vfs_next.ops.chmod_acl) {
328                 errno = ENOSYS;
329                 return -1;
330         }
331         if (!cappath) {
332                 errno = ENOMEM;
333                 return -1;
334         }
335         return SMB_VFS_NEXT_CHMOD_ACL(handle, cappath, mode);
336 }
337
338 static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T type)
339 {
340         char *cappath = capencode(talloc_tos(), path);
341
342         if (!cappath) {
343                 errno = ENOMEM;
344                 return (SMB_ACL_T)NULL;
345         }
346         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath, type);
347 }
348
349 static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
350 {
351         char *cappath = capencode(talloc_tos(), path);
352
353         if (!cappath) {
354                 errno = ENOMEM;
355                 return -1;
356         }
357         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cappath, acltype, theacl);
358 }
359
360 static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
361 {
362         char *cappath = capencode(talloc_tos(), path);
363
364         if (!cappath) {
365                 errno = ENOMEM;
366                 return -1;
367         }
368         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
369 }
370
371 static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
372 {
373         char *cappath = capencode(talloc_tos(), path);
374         char *capname = capencode(talloc_tos(), name);
375
376         if (!cappath || !capname) {
377                 errno = ENOMEM;
378                 return -1;
379         }
380         return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
381 }
382
383 static ssize_t cap_lgetxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t
384 size)
385 {
386         char *cappath = capencode(talloc_tos(), path);
387         char *capname = capencode(talloc_tos(), name);
388
389         if (!cappath || !capname) {
390                 errno = ENOMEM;
391                 return -1;
392         }
393         return SMB_VFS_NEXT_LGETXATTR(handle, cappath, capname, value, size);
394 }
395
396 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
397 {
398         char *cappath = capencode(talloc_tos(), path);
399
400         if (!cappath) {
401                 errno = ENOMEM;
402                 return -1;
403         }
404         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
405 }
406
407 static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
408 {
409         char *cappath = capencode(talloc_tos(), path);
410
411         if (!cappath) {
412                 errno = ENOMEM;
413                 return -1;
414         }
415         return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
416 }
417
418 static ssize_t cap_llistxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
419 {
420         char *cappath = capencode(talloc_tos(), path);
421
422         if (!cappath) {
423                 errno = ENOMEM;
424                 return -1;
425         }
426         return SMB_VFS_NEXT_LLISTXATTR(handle, cappath, list, size);
427 }
428
429 static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
430 {
431         char *cappath = capencode(talloc_tos(), path);
432         char *capname = capencode(talloc_tos(), name);
433
434         if (!cappath || !capname) {
435                 errno = ENOMEM;
436                 return -1;
437         }
438         return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
439 }
440
441 static int cap_lremovexattr(vfs_handle_struct *handle, const char *path, const char *name)
442 {
443         char *cappath = capencode(talloc_tos(), path);
444         char *capname = capencode(talloc_tos(), name);
445
446         if (!cappath || !capname) {
447                 errno = ENOMEM;
448                 return -1;
449         }
450         return SMB_VFS_NEXT_LREMOVEXATTR(handle, cappath, capname);
451 }
452
453 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
454 {
455         char *cappath = capencode(talloc_tos(), path);
456
457         if (!cappath) {
458                 errno = ENOMEM;
459                 return -1;
460         }
461         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
462 }
463
464 static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
465 {
466         char *cappath = capencode(talloc_tos(), path);
467         char *capname = capencode(talloc_tos(), name);
468
469         if (!cappath || !capname) {
470                 errno = ENOMEM;
471                 return -1;
472         }
473         return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
474 }
475
476 static int cap_lsetxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
477 {
478         char *cappath = capencode(talloc_tos(), path);
479         char *capname = capencode(talloc_tos(), name);
480
481         if (!cappath || !capname) {
482                 errno = ENOMEM;
483                 return -1;
484         }
485         return SMB_VFS_NEXT_LSETXATTR(handle, cappath, capname, value, size, flags);
486 }
487
488 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
489 {
490         char *cappath = capencode(talloc_tos(), path);
491
492         if (!cappath) {
493                 errno = ENOMEM;
494                 return -1;
495         }
496         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
497 }
498
499 /* VFS operations structure */
500
501 static vfs_op_tuple cap_op_tuples[] = {
502
503         /* Disk operations */
504
505         {SMB_VFS_OP(cap_disk_free),                     SMB_VFS_OP_DISK_FREE,           SMB_VFS_LAYER_TRANSPARENT},
506
507         /* Directory operations */
508
509         {SMB_VFS_OP(cap_opendir),                       SMB_VFS_OP_OPENDIR,             SMB_VFS_LAYER_TRANSPARENT},
510         {SMB_VFS_OP(cap_readdir),                       SMB_VFS_OP_READDIR,             SMB_VFS_LAYER_TRANSPARENT},
511         {SMB_VFS_OP(cap_mkdir),                 SMB_VFS_OP_MKDIR,               SMB_VFS_LAYER_TRANSPARENT},
512         {SMB_VFS_OP(cap_rmdir),                 SMB_VFS_OP_RMDIR,               SMB_VFS_LAYER_TRANSPARENT},
513
514         /* File operations */
515
516         {SMB_VFS_OP(cap_open),                          SMB_VFS_OP_OPEN,                SMB_VFS_LAYER_TRANSPARENT},
517         {SMB_VFS_OP(cap_rename),                        SMB_VFS_OP_RENAME,              SMB_VFS_LAYER_TRANSPARENT},
518         {SMB_VFS_OP(cap_stat),                          SMB_VFS_OP_STAT,                SMB_VFS_LAYER_TRANSPARENT},
519         {SMB_VFS_OP(cap_lstat),                 SMB_VFS_OP_LSTAT,               SMB_VFS_LAYER_TRANSPARENT},
520         {SMB_VFS_OP(cap_unlink),                        SMB_VFS_OP_UNLINK,              SMB_VFS_LAYER_TRANSPARENT},
521         {SMB_VFS_OP(cap_chmod),                 SMB_VFS_OP_CHMOD,               SMB_VFS_LAYER_TRANSPARENT},
522         {SMB_VFS_OP(cap_chown),                 SMB_VFS_OP_CHOWN,               SMB_VFS_LAYER_TRANSPARENT},
523         {SMB_VFS_OP(cap_lchown),                SMB_VFS_OP_LCHOWN,              SMB_VFS_LAYER_TRANSPARENT},
524         {SMB_VFS_OP(cap_chdir),                 SMB_VFS_OP_CHDIR,               SMB_VFS_LAYER_TRANSPARENT},
525         {SMB_VFS_OP(cap_ntimes),                        SMB_VFS_OP_NTIMES,              SMB_VFS_LAYER_TRANSPARENT},
526         {SMB_VFS_OP(cap_symlink),                       SMB_VFS_OP_SYMLINK,             SMB_VFS_LAYER_TRANSPARENT},
527         {SMB_VFS_OP(cap_readlink),                      SMB_VFS_OP_READLINK,            SMB_VFS_LAYER_TRANSPARENT},
528         {SMB_VFS_OP(cap_link),                          SMB_VFS_OP_LINK,                SMB_VFS_LAYER_TRANSPARENT},
529         {SMB_VFS_OP(cap_mknod),                 SMB_VFS_OP_MKNOD,               SMB_VFS_LAYER_TRANSPARENT},
530         {SMB_VFS_OP(cap_realpath),                      SMB_VFS_OP_REALPATH,            SMB_VFS_LAYER_TRANSPARENT},
531
532         /* POSIX ACL operations */
533
534         {SMB_VFS_OP(cap_chmod_acl),                     SMB_VFS_OP_CHMOD_ACL,           SMB_VFS_LAYER_TRANSPARENT},
535
536         {SMB_VFS_OP(cap_sys_acl_get_file),              SMB_VFS_OP_SYS_ACL_GET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
537         {SMB_VFS_OP(cap_sys_acl_set_file),              SMB_VFS_OP_SYS_ACL_SET_FILE,            SMB_VFS_LAYER_TRANSPARENT},
538         {SMB_VFS_OP(cap_sys_acl_delete_def_file),       SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,     SMB_VFS_LAYER_TRANSPARENT},
539
540         /* EA operations. */
541         {SMB_VFS_OP(cap_getxattr),                      SMB_VFS_OP_GETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
542         {SMB_VFS_OP(cap_lgetxattr),                     SMB_VFS_OP_LGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
543         {SMB_VFS_OP(cap_fgetxattr),                     SMB_VFS_OP_FGETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
544         {SMB_VFS_OP(cap_listxattr),                     SMB_VFS_OP_LISTXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
545         {SMB_VFS_OP(cap_llistxattr),                    SMB_VFS_OP_LLISTXATTR,                  SMB_VFS_LAYER_TRANSPARENT},
546         {SMB_VFS_OP(cap_removexattr),                   SMB_VFS_OP_REMOVEXATTR,                 SMB_VFS_LAYER_TRANSPARENT},
547         {SMB_VFS_OP(cap_lremovexattr),                  SMB_VFS_OP_LREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
548         {SMB_VFS_OP(cap_fremovexattr),                  SMB_VFS_OP_FREMOVEXATTR,                SMB_VFS_LAYER_TRANSPARENT},
549         {SMB_VFS_OP(cap_setxattr),                      SMB_VFS_OP_SETXATTR,                    SMB_VFS_LAYER_TRANSPARENT},
550         {SMB_VFS_OP(cap_lsetxattr),                     SMB_VFS_OP_LSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
551         {SMB_VFS_OP(cap_fsetxattr),                     SMB_VFS_OP_FSETXATTR,                   SMB_VFS_LAYER_TRANSPARENT},
552
553         {NULL,                                          SMB_VFS_OP_NOOP,                        SMB_VFS_LAYER_NOOP}
554 };
555
556 NTSTATUS vfs_cap_init(void);
557 NTSTATUS vfs_cap_init(void)
558 {
559         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples);
560 }
561
562 /* For CAP functions */
563 #define hex_tag ':'
564 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
565 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
566 #define is_hex(s)               ((s)[0] == hex_tag)
567
568 static unsigned char hex2bin_table[256] = {
569 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
570 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
571 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
572 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
573 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
574 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
576 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
577 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
579 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
580 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
582 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
583 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
584 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
585 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
586 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
587 };
588 static unsigned char bin2hex_table[256] = "0123456789abcdef";
589
590 /*******************************************************************
591   original code -> ":xx"  - CAP format
592 ********************************************************************/
593
594 static char *capencode(TALLOC_CTX *ctx, const char *from)
595 {
596         char *out = NULL;
597         const char *p1;
598         char *to = NULL;
599         size_t len = 0;
600
601         for (p1 = from; *p1; p1++) {
602                 if ((unsigned char)*p1 >= 0x80) {
603                         len += 3;
604                 } else {
605                         len++;
606                 }
607         }
608         len++;
609
610         to = TALLOC_ARRAY(ctx, char, len);
611         if (!to) {
612                 return NULL;
613         }
614
615         for (out = to; *from;) {
616                 /* buffer husoku error */
617                 if ((unsigned char)*from >= 0x80) {
618                         *out++ = hex_tag;
619                         *out++ = bin2hex (((*from)>>4)&0x0f);
620                         *out++ = bin2hex ((*from)&0x0f);
621                         from++;
622                 } else {
623                         *out++ = *from++;
624                 }
625         }
626         *out = '\0';
627         return to;
628 }
629
630 /*******************************************************************
631   CAP -> original code
632 ********************************************************************/
633 /* ":xx" -> a byte */
634
635 static char *capdecode(TALLOC_CTX *ctx, const char *from)
636 {
637         const char *p1;
638         char *out = NULL;
639         char *to = NULL;
640         size_t len = 0;
641
642         for (p1 = from; *p1; len++) {
643                 if (is_hex(from)) {
644                         p1 += 3;
645                 } else {
646                         p1++;
647                 }
648         }
649
650         to = TALLOC_ARRAY(ctx, char, len);
651         if (!to) {
652                 return NULL;
653         }
654
655         for (out = to; *from;) {
656                 if (is_hex(from)) {
657                         *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
658                         from += 3;
659                 } else {
660                         *out++ = *from++;
661                 }
662         }
663         *out = '\0';
664         return to;
665 }