VFS: Modify lchown to take a const struct smb_filename * instead of const char *
[sfrench/samba-autobuild/.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 #include "smbd/smbd.h"
27
28 /* cap functions */
29 static char *capencode(TALLOC_CTX *ctx, const char *from);
30 static char *capdecode(TALLOC_CTX *ctx, const char *from);
31
32 static uint64_t cap_disk_free(vfs_handle_struct *handle, const char *path,
33                               uint64_t *bsize, 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, bsize, dfree, dsize);
42 }
43
44 static int cap_get_quota(vfs_handle_struct *handle, const char *path,
45                          enum SMB_QUOTA_TYPE qtype, unid_t id,
46                          SMB_DISK_QUOTA *dq)
47 {
48         char *cappath = capencode(talloc_tos(), path);
49
50         if (!cappath) {
51                 errno = ENOMEM;
52                 return -1;
53         }
54         return SMB_VFS_NEXT_GET_QUOTA(handle, cappath, qtype, id, dq);
55 }
56
57 static DIR *cap_opendir(vfs_handle_struct *handle,
58                         const struct smb_filename *smb_fname,
59                         const char *mask,
60                         uint32_t attr)
61 {
62         char *capname = capencode(talloc_tos(), smb_fname->base_name);
63         struct smb_filename *cap_smb_fname = NULL;
64
65         if (!capname) {
66                 errno = ENOMEM;
67                 return NULL;
68         }
69         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
70                                         capname,
71                                         NULL,
72                                         NULL);
73         if (cap_smb_fname == NULL) {
74                 TALLOC_FREE(capname);
75                 errno = ENOMEM;
76                 return NULL;
77         }
78         return SMB_VFS_NEXT_OPENDIR(handle, cap_smb_fname, mask, attr);
79 }
80
81 static struct dirent *cap_readdir(vfs_handle_struct *handle,
82                                       DIR *dirp,
83                                       SMB_STRUCT_STAT *sbuf)
84 {
85         struct dirent *result;
86         struct dirent *newdirent;
87         char *newname;
88         size_t newnamelen;
89         DEBUG(3,("cap: cap_readdir\n"));
90
91         result = SMB_VFS_NEXT_READDIR(handle, dirp, NULL);
92         if (!result) {
93                 return NULL;
94         }
95
96         newname = capdecode(talloc_tos(), result->d_name);
97         if (!newname) {
98                 return NULL;
99         }
100         DEBUG(3,("cap: cap_readdir: %s\n", newname));
101         newnamelen = strlen(newname)+1;
102         newdirent = talloc_size(
103                 talloc_tos(), sizeof(struct dirent) + newnamelen);
104         if (!newdirent) {
105                 return NULL;
106         }
107         talloc_set_name_const(newdirent, "struct dirent");
108         memcpy(newdirent, result, sizeof(struct dirent));
109         memcpy(&newdirent->d_name, newname, newnamelen);
110         return newdirent;
111 }
112
113 static int cap_mkdir(vfs_handle_struct *handle,
114                 const struct smb_filename *smb_fname,
115                 mode_t mode)
116 {
117         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
118         struct smb_filename *cap_smb_fname = NULL;
119
120         if (!cappath) {
121                 errno = ENOMEM;
122                 return -1;
123         }
124
125         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
126                                         cappath,
127                                         NULL,
128                                         NULL);
129         if (cap_smb_fname == NULL) {
130                 TALLOC_FREE(cappath);
131                 errno = ENOMEM;
132                 return -1;
133         }
134
135         return SMB_VFS_NEXT_MKDIR(handle, cap_smb_fname, mode);
136 }
137
138 static int cap_rmdir(vfs_handle_struct *handle,
139                 const struct smb_filename *smb_fname)
140 {
141         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
142         struct smb_filename *cap_smb_fname = NULL;
143
144         if (!cappath) {
145                 errno = ENOMEM;
146                 return -1;
147         }
148
149         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
150                                         cappath,
151                                         NULL,
152                                         NULL);
153         if (cap_smb_fname == NULL) {
154                 TALLOC_FREE(cappath);
155                 errno = ENOMEM;
156                 return -1;
157         }
158
159         return SMB_VFS_NEXT_RMDIR(handle, cap_smb_fname);
160 }
161
162 static int cap_open(vfs_handle_struct *handle, struct smb_filename *smb_fname,
163                     files_struct *fsp, int flags, mode_t mode)
164 {
165         char *cappath;
166         char *tmp_base_name = NULL;
167         int ret;
168
169         cappath = capencode(talloc_tos(), smb_fname->base_name);
170
171         if (!cappath) {
172                 errno = ENOMEM;
173                 return -1;
174         }
175
176         tmp_base_name = smb_fname->base_name;
177         smb_fname->base_name = cappath;
178
179         DEBUG(3,("cap: cap_open for %s\n", smb_fname_str_dbg(smb_fname)));
180         ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
181
182         smb_fname->base_name = tmp_base_name;
183         TALLOC_FREE(cappath);
184
185         return ret;
186 }
187
188 static int cap_rename(vfs_handle_struct *handle,
189                       const struct smb_filename *smb_fname_src,
190                       const struct smb_filename *smb_fname_dst)
191 {
192         char *capold = NULL;
193         char *capnew = NULL;
194         struct smb_filename *smb_fname_src_tmp = NULL;
195         struct smb_filename *smb_fname_dst_tmp = NULL;
196         int ret = -1;
197
198         capold = capencode(talloc_tos(), smb_fname_src->base_name);
199         capnew = capencode(talloc_tos(), smb_fname_dst->base_name);
200         if (!capold || !capnew) {
201                 errno = ENOMEM;
202                 goto out;
203         }
204
205         /* Setup temporary smb_filename structs. */
206         smb_fname_src_tmp = cp_smb_filename(talloc_tos(), smb_fname_src);
207         if (smb_fname_src_tmp == NULL) {
208                 errno = ENOMEM;
209                 goto out;
210         }
211         smb_fname_dst_tmp = cp_smb_filename(talloc_tos(), smb_fname_dst);
212         if (smb_fname_dst_tmp == NULL) {
213                 errno = ENOMEM;
214                 goto out;
215         }
216
217         smb_fname_src_tmp->base_name = capold;
218         smb_fname_dst_tmp->base_name = capnew;
219
220         ret = SMB_VFS_NEXT_RENAME(handle, smb_fname_src_tmp,
221                                   smb_fname_dst_tmp);
222  out:
223         TALLOC_FREE(capold);
224         TALLOC_FREE(capnew);
225         TALLOC_FREE(smb_fname_src_tmp);
226         TALLOC_FREE(smb_fname_dst_tmp);
227
228         return ret;
229 }
230
231 static int cap_stat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
232 {
233         char *cappath;
234         char *tmp_base_name = NULL;
235         int ret;
236
237         cappath = capencode(talloc_tos(), smb_fname->base_name);
238
239         if (!cappath) {
240                 errno = ENOMEM;
241                 return -1;
242         }
243
244         tmp_base_name = smb_fname->base_name;
245         smb_fname->base_name = cappath;
246
247         ret = SMB_VFS_NEXT_STAT(handle, smb_fname);
248
249         smb_fname->base_name = tmp_base_name;
250         TALLOC_FREE(cappath);
251
252         return ret;
253 }
254
255 static int cap_lstat(vfs_handle_struct *handle, struct smb_filename *smb_fname)
256 {
257         char *cappath;
258         char *tmp_base_name = NULL;
259         int ret;
260
261         cappath = capencode(talloc_tos(), smb_fname->base_name);
262
263         if (!cappath) {
264                 errno = ENOMEM;
265                 return -1;
266         }
267
268         tmp_base_name = smb_fname->base_name;
269         smb_fname->base_name = cappath;
270
271         ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname);
272
273         smb_fname->base_name = tmp_base_name;
274         TALLOC_FREE(cappath);
275
276         return ret;
277 }
278
279 static int cap_unlink(vfs_handle_struct *handle,
280                       const struct smb_filename *smb_fname)
281 {
282         struct smb_filename *smb_fname_tmp = NULL;
283         char *cappath = NULL;
284         int ret;
285
286         cappath = capencode(talloc_tos(), smb_fname->base_name);
287         if (!cappath) {
288                 errno = ENOMEM;
289                 return -1;
290         }
291
292         /* Setup temporary smb_filename structs. */
293         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
294         if (smb_fname_tmp == NULL) {
295                 errno = ENOMEM;
296                 return -1;
297         }
298
299         smb_fname_tmp->base_name = cappath;
300
301         ret = SMB_VFS_NEXT_UNLINK(handle, smb_fname_tmp);
302
303         TALLOC_FREE(smb_fname_tmp);
304         return ret;
305 }
306
307 static int cap_chmod(vfs_handle_struct *handle,
308                         const struct smb_filename *smb_fname,
309                         mode_t mode)
310 {
311         struct smb_filename *cap_smb_fname = NULL;
312         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
313         int ret;
314         int saved_errno;
315
316         if (!cappath) {
317                 errno = ENOMEM;
318                 return -1;
319         }
320
321         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
322                                         cappath,
323                                         NULL,
324                                         NULL);
325         if (cap_smb_fname == NULL) {
326                 TALLOC_FREE(cappath);
327                 errno = ENOMEM;
328                 return -1;
329         }
330
331         ret = SMB_VFS_NEXT_CHMOD(handle, cap_smb_fname, mode);
332         saved_errno = errno;
333         TALLOC_FREE(cappath);
334         TALLOC_FREE(cap_smb_fname);
335         errno = saved_errno;
336         return ret;
337 }
338
339 static int cap_chown(vfs_handle_struct *handle,
340                         const struct smb_filename *smb_fname,
341                         uid_t uid,
342                         gid_t gid)
343 {
344         struct smb_filename *cap_smb_fname = NULL;
345         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
346         int ret;
347         int saved_errno;
348
349         if (!cappath) {
350                 errno = ENOMEM;
351                 return -1;
352         }
353
354         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
355                                         cappath,
356                                         NULL,
357                                         NULL);
358         if (cap_smb_fname == NULL) {
359                 TALLOC_FREE(cappath);
360                 errno = ENOMEM;
361                 return -1;
362         }
363
364         ret = SMB_VFS_NEXT_CHOWN(handle, cap_smb_fname, uid, gid);
365         saved_errno = errno;
366         TALLOC_FREE(cappath);
367         TALLOC_FREE(cap_smb_fname);
368         errno = saved_errno;
369         return ret;
370 }
371
372 static int cap_lchown(vfs_handle_struct *handle,
373                         const struct smb_filename *smb_fname,
374                         uid_t uid,
375                         gid_t gid)
376 {
377         struct smb_filename *cap_smb_fname = NULL;
378         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
379         int ret;
380         int saved_errno;
381
382         if (!cappath) {
383                 errno = ENOMEM;
384                 return -1;
385         }
386
387         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
388                                         cappath,
389                                         NULL,
390                                         NULL);
391         if (cap_smb_fname == NULL) {
392                 TALLOC_FREE(cappath);
393                 errno = ENOMEM;
394                 return -1;
395         }
396
397         ret = SMB_VFS_NEXT_LCHOWN(handle, cap_smb_fname, uid, gid);
398         saved_errno = errno;
399         TALLOC_FREE(cappath);
400         TALLOC_FREE(cap_smb_fname);
401         errno = saved_errno;
402         return ret;
403 }
404
405 static int cap_chdir(vfs_handle_struct *handle, const char *path)
406 {
407         char *cappath = capencode(talloc_tos(), path);
408
409         if (!cappath) {
410                 errno = ENOMEM;
411                 return -1;
412         }
413         DEBUG(3,("cap: cap_chdir for %s\n", path));
414         return SMB_VFS_NEXT_CHDIR(handle, cappath);
415 }
416
417 static int cap_ntimes(vfs_handle_struct *handle,
418                       const struct smb_filename *smb_fname,
419                       struct smb_file_time *ft)
420 {
421         struct smb_filename *smb_fname_tmp = NULL;
422         char *cappath = NULL;
423         int ret;
424
425         cappath = capencode(talloc_tos(), smb_fname->base_name);
426
427         if (!cappath) {
428                 errno = ENOMEM;
429                 return -1;
430         }
431
432         /* Setup temporary smb_filename structs. */
433         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
434         if (smb_fname_tmp == NULL) {
435                 errno = ENOMEM;
436                 return -1;
437         }
438
439         smb_fname_tmp->base_name = cappath;
440
441         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
442
443         TALLOC_FREE(smb_fname_tmp);
444         return ret;
445 }
446
447
448 static int cap_symlink(vfs_handle_struct *handle, const char *oldpath,
449                        const char *newpath)
450 {
451         char *capold = capencode(talloc_tos(), oldpath);
452         char *capnew = capencode(talloc_tos(), newpath);
453
454         if (!capold || !capnew) {
455                 errno = ENOMEM;
456                 return -1;
457         }
458         return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
459 }
460
461 static int cap_readlink(vfs_handle_struct *handle, const char *path,
462                         char *buf, size_t bufsiz)
463 {
464         char *cappath = capencode(talloc_tos(), path);
465
466         if (!cappath) {
467                 errno = ENOMEM;
468                 return -1;
469         }
470         return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
471 }
472
473 static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
474 {
475         char *capold = capencode(talloc_tos(), oldpath);
476         char *capnew = capencode(talloc_tos(), newpath);
477
478         if (!capold || !capnew) {
479                 errno = ENOMEM;
480                 return -1;
481         }
482         return SMB_VFS_NEXT_LINK(handle, capold, capnew);
483 }
484
485 static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
486 {
487         char *cappath = capencode(talloc_tos(), path);
488
489         if (!cappath) {
490                 errno = ENOMEM;
491                 return -1;
492         }
493         return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
494 }
495
496 static char *cap_realpath(vfs_handle_struct *handle, const char *path)
497 {
498         /* monyo need capencode'ed and capdecode'ed? */
499         char *cappath = capencode(talloc_tos(), path);
500
501         if (!cappath) {
502                 errno = ENOMEM;
503                 return NULL;
504         }
505         return SMB_VFS_NEXT_REALPATH(handle, cappath);
506 }
507
508 static int cap_chmod_acl(vfs_handle_struct *handle,
509                         const struct smb_filename *smb_fname,
510                         mode_t mode)
511 {
512         struct smb_filename *cap_smb_fname = NULL;
513         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
514         int ret;
515         int saved_errno;
516
517         /* If the underlying VFS doesn't have ACL support... */
518         if (!cappath) {
519                 errno = ENOMEM;
520                 return -1;
521         }
522         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
523                                         cappath,
524                                         NULL,
525                                         NULL);
526         if (cap_smb_fname == NULL) {
527                 TALLOC_FREE(cappath);
528                 errno = ENOMEM;
529                 return -1;
530         }
531
532         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, cap_smb_fname, mode);
533         saved_errno = errno;
534         TALLOC_FREE(cappath);
535         TALLOC_FREE(cap_smb_fname);
536         errno = saved_errno;
537         return ret;
538 }
539
540 static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle,
541                                       const char *path, SMB_ACL_TYPE_T type,
542                                       TALLOC_CTX *mem_ctx)
543 {
544         char *cappath = capencode(talloc_tos(), path);
545
546         if (!cappath) {
547                 errno = ENOMEM;
548                 return (SMB_ACL_T)NULL;
549         }
550         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath, type, mem_ctx);
551 }
552
553 static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
554 {
555         char *cappath = capencode(talloc_tos(), path);
556
557         if (!cappath) {
558                 errno = ENOMEM;
559                 return -1;
560         }
561         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cappath, acltype, theacl);
562 }
563
564 static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
565 {
566         char *cappath = capencode(talloc_tos(), path);
567
568         if (!cappath) {
569                 errno = ENOMEM;
570                 return -1;
571         }
572         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
573 }
574
575 static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
576 {
577         char *cappath = capencode(talloc_tos(), path);
578         char *capname = capencode(talloc_tos(), name);
579
580         if (!cappath || !capname) {
581                 errno = ENOMEM;
582                 return -1;
583         }
584         return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
585 }
586
587 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
588 {
589         char *cappath = capencode(talloc_tos(), path);
590
591         if (!cappath) {
592                 errno = ENOMEM;
593                 return -1;
594         }
595         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
596 }
597
598 static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
599 {
600         char *cappath = capencode(talloc_tos(), path);
601
602         if (!cappath) {
603                 errno = ENOMEM;
604                 return -1;
605         }
606         return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
607 }
608
609 static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
610 {
611         char *cappath = capencode(talloc_tos(), path);
612         char *capname = capencode(talloc_tos(), name);
613
614         if (!cappath || !capname) {
615                 errno = ENOMEM;
616                 return -1;
617         }
618         return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
619 }
620
621 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
622 {
623         char *cappath = capencode(talloc_tos(), path);
624
625         if (!cappath) {
626                 errno = ENOMEM;
627                 return -1;
628         }
629         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
630 }
631
632 static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
633 {
634         char *cappath = capencode(talloc_tos(), path);
635         char *capname = capencode(talloc_tos(), name);
636
637         if (!cappath || !capname) {
638                 errno = ENOMEM;
639                 return -1;
640         }
641         return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
642 }
643
644 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
645 {
646         char *cappath = capencode(talloc_tos(), path);
647
648         if (!cappath) {
649                 errno = ENOMEM;
650                 return -1;
651         }
652         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
653 }
654
655 static struct vfs_fn_pointers vfs_cap_fns = {
656         .disk_free_fn = cap_disk_free,
657         .get_quota_fn = cap_get_quota,
658         .opendir_fn = cap_opendir,
659         .readdir_fn = cap_readdir,
660         .mkdir_fn = cap_mkdir,
661         .rmdir_fn = cap_rmdir,
662         .open_fn = cap_open,
663         .rename_fn = cap_rename,
664         .stat_fn = cap_stat,
665         .lstat_fn = cap_lstat,
666         .unlink_fn = cap_unlink,
667         .chmod_fn = cap_chmod,
668         .chown_fn = cap_chown,
669         .lchown_fn = cap_lchown,
670         .chdir_fn = cap_chdir,
671         .ntimes_fn = cap_ntimes,
672         .symlink_fn = cap_symlink,
673         .readlink_fn = cap_readlink,
674         .link_fn = cap_link,
675         .mknod_fn = cap_mknod,
676         .realpath_fn = cap_realpath,
677         .chmod_acl_fn = cap_chmod_acl,
678         .sys_acl_get_file_fn = cap_sys_acl_get_file,
679         .sys_acl_set_file_fn = cap_sys_acl_set_file,
680         .sys_acl_delete_def_file_fn = cap_sys_acl_delete_def_file,
681         .getxattr_fn = cap_getxattr,
682         .fgetxattr_fn = cap_fgetxattr,
683         .listxattr_fn = cap_listxattr,
684         .removexattr_fn = cap_removexattr,
685         .fremovexattr_fn = cap_fremovexattr,
686         .setxattr_fn = cap_setxattr,
687         .fsetxattr_fn = cap_fsetxattr
688 };
689
690 NTSTATUS vfs_cap_init(void);
691 NTSTATUS vfs_cap_init(void)
692 {
693         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
694                                 &vfs_cap_fns);
695 }
696
697 /* For CAP functions */
698 #define hex_tag ':'
699 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
700 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
701 #define is_hex(s)               ((s)[0] == hex_tag)
702
703 static unsigned char hex2bin_table[256] = {
704 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
705 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
706 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
707 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
708 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
709 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
710 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
711 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
712 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
713 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
714 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
715 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
716 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
717 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
718 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
719 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
720 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
721 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
722 };
723 static unsigned char bin2hex_table[256] = "0123456789abcdef";
724
725 /*******************************************************************
726   original code -> ":xx"  - CAP format
727 ********************************************************************/
728
729 static char *capencode(TALLOC_CTX *ctx, const char *from)
730 {
731         char *out = NULL;
732         const char *p1;
733         char *to = NULL;
734         size_t len = 0;
735
736         for (p1 = from; *p1; p1++) {
737                 if ((unsigned char)*p1 >= 0x80) {
738                         len += 3;
739                 } else {
740                         len++;
741                 }
742         }
743         len++;
744
745         to = talloc_array(ctx, char, len);
746         if (!to) {
747                 return NULL;
748         }
749
750         for (out = to; *from;) {
751                 /* buffer husoku error */
752                 if ((unsigned char)*from >= 0x80) {
753                         *out++ = hex_tag;
754                         *out++ = bin2hex (((*from)>>4)&0x0f);
755                         *out++ = bin2hex ((*from)&0x0f);
756                         from++;
757                 } else {
758                         *out++ = *from++;
759                 }
760         }
761         *out = '\0';
762         return to;
763 }
764
765 /*******************************************************************
766   CAP -> original code
767 ********************************************************************/
768 /* ":xx" -> a byte */
769
770 static char *capdecode(TALLOC_CTX *ctx, const char *from)
771 {
772         const char *p1;
773         char *out = NULL;
774         char *to = NULL;
775         size_t len = 0;
776
777         for (p1 = from; *p1; len++) {
778                 if (is_hex(p1)) {
779                         p1 += 3;
780                 } else {
781                         p1++;
782                 }
783         }
784         len++;
785
786         to = talloc_array(ctx, char, len);
787         if (!to) {
788                 return NULL;
789         }
790
791         for (out = to; *from;) {
792                 if (is_hex(from)) {
793                         *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
794                         from += 3;
795                 } else {
796                         *out++ = *from++;
797                 }
798         }
799         *out = '\0';
800         return to;
801 }