VFS: Modify chown to take a const struct smb_filename * instead of const char *
[kai/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, const char *path, uid_t uid, gid_t gid)
373 {
374         char *cappath = capencode(talloc_tos(), path);
375
376         if (!cappath) {
377                 errno = ENOMEM;
378                 return -1;
379         }
380         return SMB_VFS_NEXT_LCHOWN(handle, cappath, uid, gid);
381 }
382
383 static int cap_chdir(vfs_handle_struct *handle, const char *path)
384 {
385         char *cappath = capencode(talloc_tos(), path);
386
387         if (!cappath) {
388                 errno = ENOMEM;
389                 return -1;
390         }
391         DEBUG(3,("cap: cap_chdir for %s\n", path));
392         return SMB_VFS_NEXT_CHDIR(handle, cappath);
393 }
394
395 static int cap_ntimes(vfs_handle_struct *handle,
396                       const struct smb_filename *smb_fname,
397                       struct smb_file_time *ft)
398 {
399         struct smb_filename *smb_fname_tmp = NULL;
400         char *cappath = NULL;
401         int ret;
402
403         cappath = capencode(talloc_tos(), smb_fname->base_name);
404
405         if (!cappath) {
406                 errno = ENOMEM;
407                 return -1;
408         }
409
410         /* Setup temporary smb_filename structs. */
411         smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
412         if (smb_fname_tmp == NULL) {
413                 errno = ENOMEM;
414                 return -1;
415         }
416
417         smb_fname_tmp->base_name = cappath;
418
419         ret = SMB_VFS_NEXT_NTIMES(handle, smb_fname_tmp, ft);
420
421         TALLOC_FREE(smb_fname_tmp);
422         return ret;
423 }
424
425
426 static int cap_symlink(vfs_handle_struct *handle, const char *oldpath,
427                        const char *newpath)
428 {
429         char *capold = capencode(talloc_tos(), oldpath);
430         char *capnew = capencode(talloc_tos(), newpath);
431
432         if (!capold || !capnew) {
433                 errno = ENOMEM;
434                 return -1;
435         }
436         return SMB_VFS_NEXT_SYMLINK(handle, capold, capnew);
437 }
438
439 static int cap_readlink(vfs_handle_struct *handle, const char *path,
440                         char *buf, size_t bufsiz)
441 {
442         char *cappath = capencode(talloc_tos(), path);
443
444         if (!cappath) {
445                 errno = ENOMEM;
446                 return -1;
447         }
448         return SMB_VFS_NEXT_READLINK(handle, cappath, buf, bufsiz);
449 }
450
451 static int cap_link(vfs_handle_struct *handle, const char *oldpath, const char *newpath)
452 {
453         char *capold = capencode(talloc_tos(), oldpath);
454         char *capnew = capencode(talloc_tos(), newpath);
455
456         if (!capold || !capnew) {
457                 errno = ENOMEM;
458                 return -1;
459         }
460         return SMB_VFS_NEXT_LINK(handle, capold, capnew);
461 }
462
463 static int cap_mknod(vfs_handle_struct *handle, const char *path, mode_t mode, SMB_DEV_T dev)
464 {
465         char *cappath = capencode(talloc_tos(), path);
466
467         if (!cappath) {
468                 errno = ENOMEM;
469                 return -1;
470         }
471         return SMB_VFS_NEXT_MKNOD(handle, cappath, mode, dev);
472 }
473
474 static char *cap_realpath(vfs_handle_struct *handle, const char *path)
475 {
476         /* monyo need capencode'ed and capdecode'ed? */
477         char *cappath = capencode(talloc_tos(), path);
478
479         if (!cappath) {
480                 errno = ENOMEM;
481                 return NULL;
482         }
483         return SMB_VFS_NEXT_REALPATH(handle, cappath);
484 }
485
486 static int cap_chmod_acl(vfs_handle_struct *handle,
487                         const struct smb_filename *smb_fname,
488                         mode_t mode)
489 {
490         struct smb_filename *cap_smb_fname = NULL;
491         char *cappath = capencode(talloc_tos(), smb_fname->base_name);
492         int ret;
493         int saved_errno;
494
495         /* If the underlying VFS doesn't have ACL support... */
496         if (!cappath) {
497                 errno = ENOMEM;
498                 return -1;
499         }
500         cap_smb_fname = synthetic_smb_fname(talloc_tos(),
501                                         cappath,
502                                         NULL,
503                                         NULL);
504         if (cap_smb_fname == NULL) {
505                 TALLOC_FREE(cappath);
506                 errno = ENOMEM;
507                 return -1;
508         }
509
510         ret = SMB_VFS_NEXT_CHMOD_ACL(handle, cap_smb_fname, mode);
511         saved_errno = errno;
512         TALLOC_FREE(cappath);
513         TALLOC_FREE(cap_smb_fname);
514         errno = saved_errno;
515         return ret;
516 }
517
518 static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle,
519                                       const char *path, SMB_ACL_TYPE_T type,
520                                       TALLOC_CTX *mem_ctx)
521 {
522         char *cappath = capencode(talloc_tos(), path);
523
524         if (!cappath) {
525                 errno = ENOMEM;
526                 return (SMB_ACL_T)NULL;
527         }
528         return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, cappath, type, mem_ctx);
529 }
530
531 static int cap_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl)
532 {
533         char *cappath = capencode(talloc_tos(), path);
534
535         if (!cappath) {
536                 errno = ENOMEM;
537                 return -1;
538         }
539         return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, cappath, acltype, theacl);
540 }
541
542 static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path)
543 {
544         char *cappath = capencode(talloc_tos(), path);
545
546         if (!cappath) {
547                 errno = ENOMEM;
548                 return -1;
549         }
550         return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, cappath);
551 }
552
553 static ssize_t cap_getxattr(vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size)
554 {
555         char *cappath = capencode(talloc_tos(), path);
556         char *capname = capencode(talloc_tos(), name);
557
558         if (!cappath || !capname) {
559                 errno = ENOMEM;
560                 return -1;
561         }
562         return SMB_VFS_NEXT_GETXATTR(handle, cappath, capname, value, size);
563 }
564
565 static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, void *value, size_t size)
566 {
567         char *cappath = capencode(talloc_tos(), path);
568
569         if (!cappath) {
570                 errno = ENOMEM;
571                 return -1;
572         }
573         return SMB_VFS_NEXT_FGETXATTR(handle, fsp, cappath, value, size);
574 }
575
576 static ssize_t cap_listxattr(vfs_handle_struct *handle, const char *path, char *list, size_t size)
577 {
578         char *cappath = capencode(talloc_tos(), path);
579
580         if (!cappath) {
581                 errno = ENOMEM;
582                 return -1;
583         }
584         return SMB_VFS_NEXT_LISTXATTR(handle, cappath, list, size);
585 }
586
587 static int cap_removexattr(vfs_handle_struct *handle, const char *path, const char *name)
588 {
589         char *cappath = capencode(talloc_tos(), path);
590         char *capname = capencode(talloc_tos(), name);
591
592         if (!cappath || !capname) {
593                 errno = ENOMEM;
594                 return -1;
595         }
596         return SMB_VFS_NEXT_REMOVEXATTR(handle, cappath, capname);
597 }
598
599 static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path)
600 {
601         char *cappath = capencode(talloc_tos(), path);
602
603         if (!cappath) {
604                 errno = ENOMEM;
605                 return -1;
606         }
607         return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, cappath);
608 }
609
610 static int cap_setxattr(vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags)
611 {
612         char *cappath = capencode(talloc_tos(), path);
613         char *capname = capencode(talloc_tos(), name);
614
615         if (!cappath || !capname) {
616                 errno = ENOMEM;
617                 return -1;
618         }
619         return SMB_VFS_NEXT_SETXATTR(handle, cappath, capname, value, size, flags);
620 }
621
622 static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp, const char *path, const void *value, size_t size, int flags)
623 {
624         char *cappath = capencode(talloc_tos(), path);
625
626         if (!cappath) {
627                 errno = ENOMEM;
628                 return -1;
629         }
630         return SMB_VFS_NEXT_FSETXATTR(handle, fsp, cappath, value, size, flags);
631 }
632
633 static struct vfs_fn_pointers vfs_cap_fns = {
634         .disk_free_fn = cap_disk_free,
635         .get_quota_fn = cap_get_quota,
636         .opendir_fn = cap_opendir,
637         .readdir_fn = cap_readdir,
638         .mkdir_fn = cap_mkdir,
639         .rmdir_fn = cap_rmdir,
640         .open_fn = cap_open,
641         .rename_fn = cap_rename,
642         .stat_fn = cap_stat,
643         .lstat_fn = cap_lstat,
644         .unlink_fn = cap_unlink,
645         .chmod_fn = cap_chmod,
646         .chown_fn = cap_chown,
647         .lchown_fn = cap_lchown,
648         .chdir_fn = cap_chdir,
649         .ntimes_fn = cap_ntimes,
650         .symlink_fn = cap_symlink,
651         .readlink_fn = cap_readlink,
652         .link_fn = cap_link,
653         .mknod_fn = cap_mknod,
654         .realpath_fn = cap_realpath,
655         .chmod_acl_fn = cap_chmod_acl,
656         .sys_acl_get_file_fn = cap_sys_acl_get_file,
657         .sys_acl_set_file_fn = cap_sys_acl_set_file,
658         .sys_acl_delete_def_file_fn = cap_sys_acl_delete_def_file,
659         .getxattr_fn = cap_getxattr,
660         .fgetxattr_fn = cap_fgetxattr,
661         .listxattr_fn = cap_listxattr,
662         .removexattr_fn = cap_removexattr,
663         .fremovexattr_fn = cap_fremovexattr,
664         .setxattr_fn = cap_setxattr,
665         .fsetxattr_fn = cap_fsetxattr
666 };
667
668 NTSTATUS vfs_cap_init(void);
669 NTSTATUS vfs_cap_init(void)
670 {
671         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap",
672                                 &vfs_cap_fns);
673 }
674
675 /* For CAP functions */
676 #define hex_tag ':'
677 #define hex2bin(c)              hex2bin_table[(unsigned char)(c)]
678 #define bin2hex(c)              bin2hex_table[(unsigned char)(c)]
679 #define is_hex(s)               ((s)[0] == hex_tag)
680
681 static unsigned char hex2bin_table[256] = {
682 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
683 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
684 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
685 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
686 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */
687 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
688 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
689 0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */
690 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
692 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */
693 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */
694 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */
695 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */
696 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */
697 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */
698 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */
699 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xf0 */
700 };
701 static unsigned char bin2hex_table[256] = "0123456789abcdef";
702
703 /*******************************************************************
704   original code -> ":xx"  - CAP format
705 ********************************************************************/
706
707 static char *capencode(TALLOC_CTX *ctx, const char *from)
708 {
709         char *out = NULL;
710         const char *p1;
711         char *to = NULL;
712         size_t len = 0;
713
714         for (p1 = from; *p1; p1++) {
715                 if ((unsigned char)*p1 >= 0x80) {
716                         len += 3;
717                 } else {
718                         len++;
719                 }
720         }
721         len++;
722
723         to = talloc_array(ctx, char, len);
724         if (!to) {
725                 return NULL;
726         }
727
728         for (out = to; *from;) {
729                 /* buffer husoku error */
730                 if ((unsigned char)*from >= 0x80) {
731                         *out++ = hex_tag;
732                         *out++ = bin2hex (((*from)>>4)&0x0f);
733                         *out++ = bin2hex ((*from)&0x0f);
734                         from++;
735                 } else {
736                         *out++ = *from++;
737                 }
738         }
739         *out = '\0';
740         return to;
741 }
742
743 /*******************************************************************
744   CAP -> original code
745 ********************************************************************/
746 /* ":xx" -> a byte */
747
748 static char *capdecode(TALLOC_CTX *ctx, const char *from)
749 {
750         const char *p1;
751         char *out = NULL;
752         char *to = NULL;
753         size_t len = 0;
754
755         for (p1 = from; *p1; len++) {
756                 if (is_hex(p1)) {
757                         p1 += 3;
758                 } else {
759                         p1++;
760                 }
761         }
762         len++;
763
764         to = talloc_array(ctx, char, len);
765         if (!to) {
766                 return NULL;
767         }
768
769         for (out = to; *from;) {
770                 if (is_hex(from)) {
771                         *out++ = (hex2bin(from[1])<<4) | (hex2bin(from[2]));
772                         from += 3;
773                 } else {
774                         *out++ = *from++;
775                 }
776         }
777         *out = '\0';
778         return to;
779 }