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