pipe opening now works with unicode
[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 /* we will delete this variable once our client side unicode support is complete */
27 extern int cli_use_unicode;
28
29 /****************************************************************************
30 copy a string from a char* src to a unicode or ascii
31 dos code page destination choosing unicode or ascii based on the 
32 cli->capabilities flag
33 return the number of bytes occupied by the string in the destination
34 flags can have:
35   CLISTR_TERMINATE means include the null termination
36   CLISTR_CONVERT   means convert from unix to dos codepage
37   CLISTR_UPPER     means uppercase in the destination
38 dest_len is the maximum length allowed in the destination. If dest_len
39 is -1 then no maxiumum is used
40 ****************************************************************************/
41 int clistr_push(struct cli_state *cli, void *dest, char *src, int dest_len, int flags)
42 {
43         int len;
44
45         /* treat a pstring as "unlimited" length */
46         if (dest_len == -1) {
47                 dest_len = sizeof(pstring);
48         }
49
50         if (clistr_align(cli, PTR_DIFF(cli->outbuf, dest))) {
51                 dest++;
52                 dest_len--;
53         }
54
55         if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
56                 /* the server doesn't want unicode */
57                 safe_strcpy(dest, src, dest_len);
58                 len = strlen(dest);
59                 if (flags & CLISTR_TERMINATE) len++;
60                 if (flags & CLISTR_CONVERT) unix_to_dos(dest,True);
61                 if (flags & CLISTR_UPPER) strupper(dest);
62                 return len;
63         }
64
65         /* the server likes unicode. give it the works */
66         if (flags & CLISTR_CONVERT) {
67                 dos_PutUniCode(dest, src, dest_len, flags & CLISTR_TERMINATE);
68         } else {
69                 ascii_to_unistr(dest, src, dest_len);
70         }
71         if (flags & CLISTR_UPPER) {
72                 strupper_w(dest);
73         }
74         len = strlen(src)*2;
75         if (flags & CLISTR_TERMINATE) len += 2;
76         return len;
77 }
78
79
80 /****************************************************************************
81 return the length that a string would occupy when copied with clistr_push()
82   CLISTR_TERMINATE means include the null termination
83   CLISTR_CONVERT   means convert from unix to dos codepage
84   CLISTR_UPPER     means uppercase in the destination
85 note that dest is only used for alignment purposes. No data is written.
86 ****************************************************************************/
87 int clistr_push_size(struct cli_state *cli, void *dest, char *src, int dest_len, int flags)
88 {
89         int len = strlen(src);
90         if (flags & CLISTR_TERMINATE) len++;
91         if (cli_use_unicode && (cli->capabilities & CAP_UNICODE)) len *= 2;
92
93         if (clistr_align(cli, PTR_DIFF(cli->outbuf, dest))) {
94                 len++;
95         }
96
97         return len;
98 }
99
100 /****************************************************************************
101 copy a string from a unicode or ascii source (depending on
102 cli->capabilities) to a char* destination
103 flags can have:
104   CLISTR_CONVERT   means convert from dos to unix codepage
105   CLISTR_TERMINATE means the string in src is null terminated
106 if CLISTR_TERMINATE is set then src_len is ignored
107 src_len is the length of the source area in bytes
108 return the number of bytes occupied by the string in src
109 ****************************************************************************/
110 int clistr_pull(struct cli_state *cli, char *dest, void *src, int dest_len, int src_len, int flags)
111 {
112         int len;
113
114         if (dest_len == -1) {
115                 dest_len = sizeof(pstring);
116         }
117
118         if (clistr_align(cli, PTR_DIFF(cli->inbuf, src))) {
119                 src++;
120                 if (src_len > 0) src_len--;
121         }
122
123         if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
124                 /* the server doesn't want unicode */
125                 if (flags & CLISTR_TERMINATE) {
126                         safe_strcpy(dest, src, dest_len);
127                         len = strlen(src)+1;
128                 } else {
129                         if (src_len > dest_len) src_len = dest_len;
130                         len = src_len;
131                         memcpy(dest, src, len);
132                         dest[len] = 0;
133                 }
134                 if (flags & CLISTR_CONVERT) dos_to_unix(dest,True);
135                 return len;
136         }
137
138         if (flags & CLISTR_TERMINATE) {
139                 unistr_to_ascii(dest, src, dest_len);
140                 len = strlen(dest)*2 + 2;
141         } else {
142                 int i, c;
143                 if (dest_len < src_len) src_len = dest_len;
144                 for (i=0; i < src_len; i += 2) {
145                         c = SVAL(src, i);
146                         *dest++ = c;
147                 }
148                 *dest++ = 0;
149                 len = src_len;
150         }
151         if (flags & CLISTR_CONVERT) dos_to_unix(dest,True);
152         return len;
153 }
154
155 /****************************************************************************
156 return the length that a string would occupy (not including the null)
157 when copied with clistr_pull()
158 if src_len is -1 then assume the source is null terminated
159 ****************************************************************************/
160 int clistr_pull_size(struct cli_state *cli, void *src, int src_len)
161 {
162         if (clistr_align(cli, PTR_DIFF(cli->inbuf, src))) {
163                 src++;
164                 if (src_len > 0) src_len--;
165         }
166
167         if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) {
168                 return strlen(src);
169         }       
170         return strlen_w(src);
171 }
172
173 /****************************************************************************
174 return an alignment of either 0 or 1
175 if unicode is not negotiated then return 0
176 otherwise return 1 if offset is off
177 ****************************************************************************/
178 int clistr_align(struct cli_state *cli, int offset)
179 {
180         if (!cli_use_unicode || !(cli->capabilities & CAP_UNICODE)) return 0;
181         return offset & 1;
182 }