1/*
2Copyright 1989, 1998  The Open Group
3
4Permission to use, copy, modify, distribute, and sell this software and its
5documentation for any purpose is hereby granted without fee, provided that
6the above copyright notice appear in all copies and that both that
7copyright notice and this permission notice appear in supporting
8documentation.
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
16OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19
20Except as contained in this notice, the name of The Open Group shall not be
21used in advertising or otherwise to promote the sale, use or other dealings
22in this Software without prior written authorization from The Open Group.
23 *
24 * Author:  Keith Packard, MIT X Consortium
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <X11/Xos.h>
31#include <X11/X.h>
32#include <X11/Xmd.h>
33#include <X11/Xdmcp.h>
34#include <stdlib.h>
35
36int
37XdmcpReadHeader (XdmcpBufferPtr buffer, XdmcpHeaderPtr header)
38{
39    if (XdmcpReadCARD16 (buffer, &header->version) &&
40        XdmcpReadCARD16 (buffer, &header->opcode) &&
41	XdmcpReadCARD16 (buffer, &header->length))
42	return TRUE;
43    return FALSE;
44}
45
46int
47XdmcpReadRemaining (const XdmcpBufferPtr  buffer)
48{
49    return buffer->count - buffer->pointer;
50}
51
52int
53XdmcpReadARRAY8 (XdmcpBufferPtr buffer, ARRAY8Ptr array)
54{
55    int	    i;
56
57    /*
58     * When returning FALSE, guarantee that array->data = 0.
59     * This allows the user to safely call XdmcpDisposeARRAY8(array)
60     * regardless of the return value below.
61     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
62     * so we must guarantee that array->data is NULL or a malloced pointer.
63     */
64    if (!XdmcpReadCARD16 (buffer, &array->length)) {
65 	array->data = NULL;
66	return FALSE;
67    }
68    if (!array->length)
69    {
70	array->data = NULL;
71	return TRUE;
72    }
73    array->data = (CARD8 *) malloc(array->length * sizeof (CARD8));
74    if (!array->data)
75	return FALSE;
76    for (i = 0; i < (int)array->length; i++)
77    {
78	if (!XdmcpReadCARD8 (buffer, &array->data[i]))
79	{
80	    free(array->data);
81	    array->data = NULL;
82	    array->length = 0;
83	    return FALSE;
84	}
85    }
86    return TRUE;
87}
88
89int
90XdmcpReadARRAY16 (XdmcpBufferPtr buffer, ARRAY16Ptr array)
91{
92    int	    i;
93
94    /*
95     * When returning FALSE, guarantee that array->data = 0.
96     * This allows the user to safely call XdmcpDisposeARRAY16(array)
97     * regardless of the return value below.
98     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
99     * so we must guarantee that array->data is NULL or a malloced pointer.
100     */
101    if (!XdmcpReadCARD8 (buffer, &array->length)) {
102	array->data = NULL;
103	return FALSE;
104    }
105    if (!array->length)
106    {
107	array->data = NULL;
108	return TRUE;
109    }
110    array->data = (CARD16 *) malloc(array->length * sizeof (CARD16));
111    if (!array->data)
112	return FALSE;
113    for (i = 0; i < (int)array->length; i++)
114    {
115	if (!XdmcpReadCARD16 (buffer, &array->data[i]))
116	{
117	    free(array->data);
118	    array->data = NULL;
119	    array->length = 0;
120	    return FALSE;
121	}
122    }
123    return TRUE;
124}
125
126int
127XdmcpReadARRAY32 (XdmcpBufferPtr buffer, ARRAY32Ptr array)
128{
129    int	    i;
130
131    /*
132     * When returning FALSE, guarantee that array->data = 0.
133     * This allows the user to safely call XdmcpDisposeARRAY32(array)
134     * regardless of the return value below.
135     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
136     * so we must guarantee that array->data is NULL or a malloced pointer.
137     */
138    if (!XdmcpReadCARD8 (buffer, &array->length)) {
139	array->data = NULL;
140	return FALSE;
141    }
142    if (!array->length)
143    {
144	array->data = NULL;
145	return TRUE;
146    }
147    array->data = (CARD32 *) malloc(array->length * sizeof (CARD32));
148    if (!array->data)
149	return FALSE;
150    for (i = 0; i < (int)array->length; i++)
151    {
152	if (!XdmcpReadCARD32 (buffer, &array->data[i]))
153	{
154	    free(array->data);
155	    array->data = NULL;
156	    array->length = 0;
157	    return FALSE;
158	}
159    }
160    return TRUE;
161}
162
163int
164XdmcpReadARRAYofARRAY8 (XdmcpBufferPtr buffer, ARRAYofARRAY8Ptr array)
165{
166    CARD8    i;
167
168    /*
169     * When returning FALSE, guarantee that array->data = 0.
170     * This allows the user to safely call XdmcpDisposeARRAYofARRAY8(array)
171     * regardless of the return value below.
172     * Note that XdmcpDisposeARRAY*(array) will call free(array->data),
173     * so we must guarantee that array->data is NULL or a malloced pointer.
174     */
175    if (!XdmcpReadCARD8 (buffer, &array->length)) {
176	array->data = NULL;
177	return FALSE;
178    }
179    if (!array->length)
180    {
181	array->data = NULL;
182	return TRUE;
183    }
184    array->data = (ARRAY8 *) malloc(array->length * sizeof (ARRAY8));
185    if (!array->data)
186	return FALSE;
187    for (i = 0; i < array->length; i++)
188    {
189	if (!XdmcpReadARRAY8 (buffer, &array->data[i]))
190	{
191	    /*
192	     * We must free all of the arrays allocated thus far in the loop
193	     * and free array->data and finally set array->data = 0;
194	     * The easiest way to do this is to reset the length and call
195	     * XdmcpDisposeARRAYofARRAY8(array).
196	     */
197	    array->length = i;
198	    XdmcpDisposeARRAYofARRAY8(array);
199	    return FALSE;
200	}
201    }
202    return TRUE;
203}
204
205int
206XdmcpReadCARD8 (XdmcpBufferPtr buffer, CARD8Ptr valuep)
207{
208    if (buffer->pointer >= buffer->count)
209	return FALSE;
210    *valuep = (CARD8) buffer->data[buffer->pointer++];
211    return TRUE;
212}
213
214int
215XdmcpReadCARD16 (XdmcpBufferPtr buffer, CARD16Ptr valuep)
216{
217    CARD8   high, low;
218
219    if (XdmcpReadCARD8 (buffer, &high) &&
220        XdmcpReadCARD8 (buffer, &low))
221    {
222	*valuep = (((CARD16) high) << 8) | ((CARD16) low);
223	return TRUE;
224    }
225    return FALSE;
226}
227
228int
229XdmcpReadCARD32 (XdmcpBufferPtr buffer, CARD32Ptr valuep)
230{
231    CARD8   byte0, byte1, byte2, byte3;
232    if (XdmcpReadCARD8 (buffer, &byte0) &&
233        XdmcpReadCARD8 (buffer, &byte1) &&
234	XdmcpReadCARD8 (buffer, &byte2) &&
235	XdmcpReadCARD8 (buffer, &byte3))
236    {
237	*valuep = (((CARD32) byte0) << 24) |
238		  (((CARD32) byte1) << 16) |
239		  (((CARD32) byte2) << 8) |
240		  (((CARD32) byte3));
241	return TRUE;
242    }
243    return FALSE;
244}
245