added STR_ASCII flag to srvstr_pull()
[sfrench/samba-autobuild/.git] / source / smbd / srvstr.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    server specific 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() (SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS)
27
28 /****************************************************************************
29 copy a string from a char* src to a unicode or ascii
30 dos code page destination choosing unicode or ascii based on the 
31 FLAGS2_UNICODE_STRINGS bit in inbuf
32 return the number of bytes occupied by the string in the destination
33 flags can have:
34   STR_TERMINATE means include the null termination
35   STR_CONVERT   means convert from unix to dos codepage
36   STR_UPPER     means uppercase in the destination
37   STR_ASCII     use ascii even with unicode servers
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 srvstr_push(void *inbuf, void *outbuf, void *dest, const char *src, int dest_len, int flags)
42 {
43         int len=0;
44
45         /* treat a pstring as "unlimited" length */
46         if (dest_len == -1) {
47                 dest_len = sizeof(pstring);
48         }
49
50         if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(dest, outbuf))) {
51                 *(char *)dest = 0;
52                 dest++;
53                 dest_len--;
54                 len++;
55         }
56
57         if ((flags & STR_ASCII) || !UNICODE_FLAG()) {
58                 /* the client doesn't want unicode */
59                 safe_strcpy(dest, src, dest_len);
60                 len = strlen(dest);
61                 if (flags & STR_TERMINATE) len++;
62                 if (flags & STR_CONVERT) unix_to_dos(dest,True);
63                 if (flags & STR_UPPER) strupper(dest);
64                 return len;
65         }
66
67         /* the server likes unicode. give it the works */
68         if (flags & STR_CONVERT) {
69                 dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
70         } else {
71                 ascii_to_unistr(dest, src, dest_len);
72         }
73         if (flags & STR_UPPER) {
74                 strupper_w(dest);
75         }
76         len += strlen(src)*2;
77         if (flags & STR_TERMINATE) len += 2;
78         return len;
79 }
80
81
82 /****************************************************************************
83 return the length that a string would occupy when copied with srvstr_push()
84   STR_TERMINATE means include the null termination
85   STR_CONVERT   means convert from unix to dos codepage
86   STR_UPPER     means uppercase in the destination
87 note that dest is only used for alignment purposes. No data is written.
88 ****************************************************************************/
89 int srvstr_push_size(void *inbuf, void *outbuf, 
90                      const void *dest, const char *src, int dest_len, int flags)
91 {
92         int len = strlen(src);
93         if (flags & STR_TERMINATE) len++;
94         if (!(flags & STR_ASCII) && UNICODE_FLAG()) len *= 2;
95
96         if (!(flags & STR_ASCII) && dest && srvstr_align(inbuf, PTR_DIFF(outbuf, dest))) {
97                 len++;
98         }
99
100         return len;
101 }
102
103 /****************************************************************************
104 copy a string from a unicode or ascii source (depending on flg2) 
105 to a char* destination
106 flags can have:
107   STR_CONVERT   means convert from dos to unix codepage
108   STR_TERMINATE means the string in src is null terminated
109   STR_UNICODE   means to force as unicode
110 if STR_TERMINATE is set then src_len is ignored
111 src_len is the length of the source area in bytes
112 return the number of bytes occupied by the string in src
113 ****************************************************************************/
114 int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags)
115 {
116         int len;
117
118         if (dest_len == -1) {
119                 dest_len = sizeof(pstring);
120         }
121
122         if (!(flags & STR_ASCII) && srvstr_align(inbuf, PTR_DIFF(src, inbuf))) {
123                 src++;
124                 if (src_len > 0) src_len--;
125         }
126
127         if ((flags & STR_ASCII) || (!(flags & STR_UNICODE) && !UNICODE_FLAG())) {
128                 /* the server doesn't want unicode */
129                 if (flags & STR_TERMINATE) {
130                         safe_strcpy(dest, src, dest_len);
131                         len = strlen(src)+1;
132                 } else {
133                         if (src_len > dest_len) src_len = dest_len;
134                         len = src_len;
135                         memcpy(dest, src, len);
136                         dest[len] = 0;
137                 }
138                 if (flags & STR_CONVERT) dos_to_unix(dest,True);
139                 return len;
140         }
141
142         if (flags & STR_TERMINATE) {
143                 unistr_to_ascii(dest, src, dest_len);
144                 len = strlen(dest)*2 + 2;
145         } else {
146                 int i, c;
147                 if (dest_len*2 < src_len) src_len = 2*dest_len;
148                 for (i=0; i < src_len; i += 2) {
149                         c = SVAL(src, i);
150                         *dest++ = c;
151                 }
152                 *dest++ = 0;
153                 len = src_len;
154         }
155         if (flags & STR_CONVERT) dos_to_unix(dest,True);
156         return len;
157 }
158
159 /****************************************************************************
160 return the length that a string would occupy (not including the null)
161 when copied with srvstr_pull()
162 if src_len is -1 then assume the source is null terminated
163 ****************************************************************************/
164 int srvstr_pull_size(void *inbuf, const void *src, int src_len)
165 {
166         if (srvstr_align(inbuf, PTR_DIFF(src, inbuf))) {
167                 src++;
168                 if (src_len > 0) src_len--;
169         }
170
171         if (!UNICODE_FLAG()) {
172                 return strlen(src);
173         }       
174         return strlen_w(src);
175 }
176
177 /****************************************************************************
178 return an alignment of either 0 or 1
179 if unicode is not negotiated then return 0
180 otherwise return 1 if offset is off
181 ****************************************************************************/
182 int srvstr_align(void *inbuf, int offset)
183 {
184         if (!UNICODE_FLAG()) return 0;
185         return offset & 1;
186 }