Added STR_NOALIGN flags to clistr and srvstr fns. Yes, NT actually does
[ira/wip.git] / source3 / 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(buf, flags) (!(flags & STR_ASCII) && \
27                                   ((flags & STR_UNICODE || \
28                                    (SVAL(buf, smb_flg2) & FLAGS2_UNICODE_STRINGS))))
29
30 /****************************************************************************
31 return an alignment of either 0 or 1
32 if unicode is not negotiated then return 0
33 otherwise return 1 if offset is off
34 ****************************************************************************/
35 static int srvstr_align(void *inbuf, int offset, int flags)
36 {
37         if ((flags & STR_NOALIGN) || !UNICODE_FLAG(inbuf, flags)) return 0;
38         return offset & 1;
39 }
40
41 /****************************************************************************
42 copy a string from a char* src to a unicode or ascii
43 dos code page destination choosing unicode or ascii based on the 
44 FLAGS2_UNICODE_STRINGS bit in inbuf
45 return the number of bytes occupied by the string in the destination
46 flags can have:
47   STR_TERMINATE means include the null termination
48   STR_CONVERT   means convert from unix to dos codepage
49   STR_UPPER     means uppercase in the destination
50   STR_ASCII     use ascii even with unicode servers
51   STR_UNICODE   means to force as unicode
52   STR_NOALIGN   means don't do alignment
53 dest_len is the maximum length allowed in the destination. If dest_len
54 is -1 then no maxiumum is used
55 ****************************************************************************/
56 int srvstr_push(void *outbuf, void *dest, const char *src, int dest_len, int flags)
57 {
58         int len=0;
59
60         /* treat a pstring as "unlimited" length */
61         if (dest_len == -1) {
62                 dest_len = sizeof(pstring);
63         }
64
65         if (srvstr_align(outbuf, PTR_DIFF(dest, outbuf), flags)) {
66                 *(char *)dest = 0;
67                 dest = (void *)((char *)dest + 1);
68                 dest_len--;
69                 len++;
70         }
71
72         if (!UNICODE_FLAG(outbuf, flags)) {
73                 /* the client doesn't want unicode */
74                 safe_strcpy(dest, src, dest_len);
75                 len = strlen(dest);
76                 if (flags & STR_TERMINATE) len++;
77                 if (flags & STR_CONVERT) unix_to_dos(dest,True);
78                 if (flags & STR_UPPER) strupper(dest);
79                 return len;
80         }
81
82         /* the server likes unicode. give it the works */
83         if (flags & STR_CONVERT) {
84                 dos_PutUniCode(dest, src, dest_len, flags & STR_TERMINATE);
85         } else {
86                 ascii_to_unistr(dest, src, dest_len);
87         }
88         if (flags & STR_UPPER) {
89                 strupper_w(dest);
90         }
91         len += strlen(src)*2;
92         if (flags & STR_TERMINATE) len += 2;
93         return len;
94 }
95
96 /****************************************************************************
97 copy a string from a unicode or ascii source (depending on flg2) 
98 to a char* destination
99 flags can have:
100   STR_CONVERT   means convert from dos to unix codepage
101   STR_TERMINATE means the string in src is null terminated
102   STR_UNICODE   means to force as unicode
103   STR_NOALIGN   means don't do alignment
104 if STR_TERMINATE is set then src_len is ignored
105 src_len is the length of the source area in bytes
106 return the number of bytes occupied by the string in src
107 ****************************************************************************/
108 int srvstr_pull(void *inbuf, char *dest, const void *src, int dest_len, int src_len, int flags)
109 {
110         int len;
111
112         if (dest_len == -1) {
113                 dest_len = sizeof(pstring);
114         }
115
116         if (srvstr_align(inbuf, PTR_DIFF(src, inbuf), flags)) {
117                 src = (void *)((char *)src + 1);
118                 if (src_len > 0) src_len--;
119         }
120
121         if (!UNICODE_FLAG(inbuf, flags)) {
122                 /* the server doesn't want unicode */
123                 if (flags & STR_TERMINATE) {
124                         safe_strcpy(dest, src, dest_len);
125                         len = strlen(src)+1;
126                 } else {
127                         if (src_len > dest_len) src_len = dest_len;
128                         len = src_len;
129                         memcpy(dest, src, len);
130                         dest[len] = 0;
131                 }
132                 if (flags & STR_CONVERT) dos_to_unix(dest,True);
133                 return len;
134         }
135
136         if (flags & STR_TERMINATE) {
137                 unistr_to_ascii(dest, src, dest_len);
138                 len = strlen(dest)*2 + 2;
139         } else {
140                 int i, c;
141                 if (dest_len*2 < src_len) src_len = 2*dest_len;
142                 for (i=0; i < src_len; i += 2) {
143                         c = SVAL(src, i);
144                         *dest++ = c;
145                 }
146                 *dest++ = 0;
147                 len = src_len;
148         }
149         if (flags & STR_CONVERT) dos_to_unix(dest,True);
150         return len;
151 }
152
153 /****************************************************************************
154 these are useful for replacing all those StrnCpy() ops for copying data
155 to/from the wire 
156 ****************************************************************************/
157
158 int srvstr_push_ascii(void *dest, const char *src, int dest_len)
159 {
160         return srvstr_push(NULL, dest, src, dest_len, 
161                            STR_ASCII|STR_CONVERT|STR_TERMINATE);
162 }
163
164 int srvstr_pull_ascii(char *dest, const void *src, int dest_len)
165 {
166         return srvstr_pull(NULL, dest, src, dest_len, -1,
167                            STR_ASCII|STR_CONVERT|STR_TERMINATE);
168 }