Insure caught the fact that PTRDIFFs were being done between two unrelated
[metze/samba/wip.git] / source3 / libsmb / clistr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    client string routines
5    Copyright (C) Andrew Tridgell 2001
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 #define UNICODE_FLAG(cli, flags) (!(flags & STR_ASCII) && \
27                                   ((flags & STR_UNICODE || \
28                                    (SVAL(cli->outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS))))
29
30 /****************************************************************************
31 copy a string from a char* src to a unicode or ascii
32 dos code page destination choosing unicode or ascii based on the 
33 cli->capabilities flag
34 return the number of bytes occupied by the string in the destination
35 flags can have:
36   STR_TERMINATE means include the null termination
37   STR_CONVERT   means convert from unix to dos codepage
38   STR_UPPER     means uppercase in the destination
39   STR_ASCII     use ascii even with unicode servers
40   STR_NOALIGN   means don't do alignment
41 dest_len is the maximum length allowed in the destination. If dest_len
42 is -1 then no maxiumum is used
43 ****************************************************************************/
44 int clistr_push(struct cli_state *cli, void *dest, const char *src, int dest_len, int flags)
45 {
46         int len=0;
47
48         /* treat a pstring as "unlimited" length */
49         if (dest_len == -1) {
50                 dest_len = sizeof(pstring);
51         }
52
53         if (clistr_align_out(cli, dest, flags)) {
54                 *(char *)dest = 0;
55                 dest = (void *)((char *)dest + 1);
56                 dest_len--;
57                 len++;
58         }
59
60         if (!UNICODE_FLAG(cli, flags)) {
61                 /* the server doesn't want unicode */
62                 safe_strcpy(dest, src, dest_len);
63                 len = strlen(dest);
64                 if (flags & STR_TERMINATE) len++;
65                 if (flags & STR_CONVERT) unix_to_dos(dest,True);
66                 if (flags & STR_UPPER) strupper(dest);
67                 return len;
68         }
69
70         /* the server likes unicode. give it the works */
71         if (flags & STR_CONVERT) {
72                 dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
73         } else {
74                 ascii_to_unistr(dest, src, dest_len);
75         }
76         if (flags & STR_UPPER) {
77                 strupper_w(dest);
78         }
79         len += strlen(src)*2;
80         if (flags & STR_TERMINATE) len += 2;
81         return len;
82 }
83
84 /****************************************************************************
85 copy a string from a unicode or ascii source (depending on
86 cli->capabilities) to a char* destination
87 flags can have:
88   STR_CONVERT   means convert from dos to unix codepage
89   STR_TERMINATE means the string in src is null terminated
90   STR_UNICODE   means to force as unicode
91   STR_NOALIGN   means don't do alignment
92 if STR_TERMINATE is set then src_len is ignored
93 src_len is the length of the source area in bytes
94 return the number of bytes occupied by the string in src
95 ****************************************************************************/
96 int clistr_pull(struct cli_state *cli, char *dest, const void *src, int dest_len, int src_len, int flags)
97 {
98         int len;
99
100         if (dest_len == -1) {
101                 dest_len = sizeof(pstring);
102         }
103
104         if (clistr_align_in(cli, src, flags)) {
105                 src = (const void *)((const char *)src + 1);
106                 if (src_len > 0) src_len--;
107         }
108
109         if (!UNICODE_FLAG(cli, flags)) {
110                 /* the server doesn't want unicode */
111                 if (flags & STR_TERMINATE) {
112                         safe_strcpy(dest, src, dest_len);
113                         len = strlen(src)+1;
114                 } else {
115                         if (src_len > dest_len) src_len = dest_len;
116                         len = src_len;
117                         memcpy(dest, src, len);
118                         dest[len] = 0;
119                 }
120                 if (flags & STR_CONVERT) 
121                         safe_strcpy(dest,dos_to_unix(dest,False),dest_len);
122                 return len;
123         }
124
125         if (flags & STR_TERMINATE) {
126                 unistr_to_ascii(dest, src, dest_len);
127                 len = strlen(dest)*2 + 2;
128         } else {
129                 int i, c;
130                 if (dest_len*2 < src_len) src_len = 2*dest_len;
131                 for (i=0; i < src_len; i += 2) {
132                         c = SVAL(src, i);
133                         *dest++ = c;
134                 }
135                 *dest++ = 0;
136                 len = src_len;
137         }
138         if (flags & STR_CONVERT)
139                 safe_strcpy(dest,dos_to_unix(dest,False),dest_len);
140         return len;
141 }
142
143
144 /****************************************************************************
145 return an alignment of either 0 or 1
146 if unicode is not negotiated then return 0
147 otherwise return 1 if offset is off
148 ****************************************************************************/
149 static int clistr_align(struct cli_state *cli, char *buf, const void *p, int flags)
150 {
151         if ((flags & STR_NOALIGN) || !UNICODE_FLAG(cli, flags)) return 0;
152         return PTR_DIFF(p, buf) & 1;
153 }
154
155 int clistr_align_out(struct cli_state *cli, const void *p, int flags)
156 {
157         return clistr_align(cli, cli->outbuf, p, flags);
158 }
159
160 int clistr_align_in(struct cli_state *cli, const void *p, int flags)
161 {
162         return clistr_align(cli, cli->inbuf, p, flags);
163 }
164
165