1/*
2 * Copyright 1990 Network Computing Devices;
3 * Portions Copyright 1987 by Digital Equipment Corporation
4 *
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation, and that the names of Network Computing
10 * Devices or Digital not be used in advertising or publicity pertaining
11 * to distribution of the software without specific, written prior
12 * permission. Network Computing Devices or Digital make no representations
13 * about the suitability of this software for any purpose.  It is provided
14 * "as is" without express or implied warranty.
15 *
16 * NETWORK COMPUTING DEVICES AND  DIGITAL DISCLAIM ALL WARRANTIES WITH
17 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES
19 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23 * SOFTWARE.
24 */
25
26/*
27
28Copyright 1987, 1998  The Open Group
29
30Permission to use, copy, modify, distribute, and sell this software and its
31documentation for any purpose is hereby granted without fee, provided that
32the above copyright notice appear in all copies and that both that
33copyright notice and this permission notice appear in supporting
34documentation.
35
36The above copyright notice and this permission notice shall be included in
37all copies or substantial portions of the Software.
38
39THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
42OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
43AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
44CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
45
46Except as contained in this notice, the name of The Open Group shall not be
47used in advertising or otherwise to promote the sale, use or other dealings
48in this Software without prior written authorization from The Open Group.
49
50*/
51#ifdef HAVE_CONFIG_H
52#include <config.h>
53#endif
54#include	"FSlibint.h"
55
56char      **
57FSListFontsWithXInfo(
58    FSServer		  *svr,
59    const char		  *pattern,
60    int			   maxNames,
61    int			  *count,
62    FSXFontInfoHeader	***info,
63    FSPropInfo		***pprops,
64    FSPropOffset	***offsets,
65    unsigned char	***prop_data)
66{
67    int         i;
68    size_t      size = 0;
69    FSXFontInfoHeader **fhdr = (FSXFontInfoHeader **) NULL;
70    FSPropInfo **pi = (FSPropInfo **) NULL;
71    FSPropOffset **po = (FSPropOffset **) NULL;
72    unsigned char **pd = (unsigned char **) NULL;
73    char      **flist = NULL;
74    fsListFontsWithXInfoReply reply;
75    fsListFontsWithXInfoReq *req;
76    fsPropInfo local_pi;
77    fsPropOffset local_po;
78    Status status;
79    Bool eat_data = True;
80
81    GetReq(ListFontsWithXInfo, req);
82    req->maxNames = (CARD32) maxNames;
83    req->nbytes = 0;
84    if (pattern != NULL) {
85        size_t nbytes;
86
87#ifdef HAVE_STRNLEN
88        nbytes = strnlen(pattern, FSMaxRequestBytes(svr));
89#else
90        nbytes = strlen(pattern);
91#endif
92
93        if (nbytes <= (FSMaxRequestBytes(svr) -
94                       SIZEOF(fsListFontsWithXInfoReq))) {
95            req->nbytes = (CARD16) nbytes;
96            req->length += (CARD16) ((nbytes + 3) >> 2);
97            _FSSend(svr, pattern, (long) nbytes);
98        }
99    }
100
101    for (i = 0;; i++) {
102	if (FSProtocolVersion(svr) > 1)
103	{
104	    status = _FSReply(svr, (fsReply *) &reply, 0, fsFalse);
105	    if (status != 0  &&  reply.nameLength == 0)	/* got last reply */
106		break;
107	    if (status)
108		_FSRead(svr, ((char *) &reply) + SIZEOF(fsGenericReply),
109			SIZEOF(fsListFontsWithXInfoReply) -
110			SIZEOF(fsGenericReply));
111	} else {
112	    status = _FSReply(svr, (fsReply *) & reply,
113			      ((SIZEOF(fsListFontsWithXInfoReply) -
114				SIZEOF(fsGenericReply)) >> 2), fsFalse);
115	}
116	if (!status) {
117	    eat_data = False;
118	    goto badmem;
119	}
120	if (reply.nameLength == 0)	/* got last reply in version 1 */
121	    break;
122	if ((i + reply.nReplies) >= size) {
123
124	    if (reply.nReplies > SIZE_MAX - i - 1)
125		goto badmem;
126	    size = i + reply.nReplies + 1;
127
128	    if (size > SIZE_MAX / sizeof(char *))
129		goto badmem;
130
131	    if (fhdr) {
132#define ResizeArray(var, type) { \
133		    type **tmp = FSreallocarray(var, size, sizeof(type *)); \
134		    if (tmp)						\
135			var = tmp;					\
136		    else						\
137			goto badmem;					\
138		}
139
140		ResizeArray(fhdr, FSXFontInfoHeader)
141		ResizeArray(flist, char)
142		ResizeArray(pi, FSPropInfo)
143		ResizeArray(po, FSPropOffset)
144		ResizeArray(pd, unsigned char)
145	    } else {
146#define InitArray(var, type) \
147		if ((var = FSmallocarray(size, sizeof(type *))) == NULL) { \
148		    goto badmem;					\
149		}
150
151		InitArray(fhdr, FSXFontInfoHeader)
152		InitArray(flist, char)
153		InitArray(pi, FSPropInfo)
154		InitArray(po, FSPropOffset)
155		InitArray(pd, unsigned char)
156	    }
157	}
158	fhdr[i] = FSmalloc(sizeof(FSXFontInfoHeader));
159	if (!fhdr[i]) {
160	    goto badmem;
161	}
162	FSUnpack_XFontInfoHeader(&reply, fhdr[i], FSProtocolVersion(svr));
163
164	/* alloc space for the name */
165	flist[i] = FSmalloc(reply.nameLength + 1);
166	if (!flist[i])
167	    goto cleanfhdr;
168	if (FSProtocolVersion(svr) == 1)
169	{
170	    /* get the name */
171	    _FSReadPad(svr, flist[i], (long) reply.nameLength);
172	    flist[i][reply.nameLength] = '\0';
173	}
174
175	pi[i] = FSmalloc(sizeof(FSPropInfo));
176	if (!pi[i])
177	    goto cleanflist;
178	_FSReadPad(svr, (char *) &local_pi, SIZEOF(fsPropInfo));
179	pi[i]->num_offsets = local_pi.num_offsets;
180	pi[i]->data_len = local_pi.data_len;
181
182#if SIZE_MAX <= UINT_MAX
183	if (pi[i]->num_offsets > SIZE_MAX / sizeof(FSPropOffset))
184	    goto cleanpi;
185#endif
186
187	po[i] = FSmallocarray(pi[i]->num_offsets, sizeof(FSPropOffset));
188	if (!po[i])
189	    goto cleanpi;
190	pd[i] = FSmalloc(pi[i]->data_len);
191	if (!pd[i])
192	    goto cleanpo;
193	/* get offsets */
194	for (unsigned int j = 0; j < pi[i]->num_offsets; j++)
195	{
196	    _FSReadPad(svr, (char *) &local_po, SIZEOF(fsPropOffset));
197	    po[i][j].name.position = local_po.name.position;
198	    po[i][j].name.length = local_po.name.length;
199	    po[i][j].value.position = local_po.value.position;
200	    po[i][j].value.length = local_po.value.length;
201	    po[i][j].type = local_po.type;
202	}
203
204	/* get prop data */
205	if (FSProtocolVersion(svr) == 1)
206	    _FSReadPad(svr, (char *) pd[i], pi[i]->data_len);
207	else
208	    _FSRead(svr, (char *) pd[i], pi[i]->data_len);
209
210	if (FSProtocolVersion(svr) != 1)
211	{
212	    unsigned long	nbytes;
213
214	    /* get the name */
215	    _FSRead(svr, flist[i], (long) reply.nameLength);
216	    flist[i][reply.nameLength] = '\0';
217
218	    nbytes = pi[i]->data_len + reply.nameLength;
219	    _FSEatData(svr, (unsigned long) (((nbytes+3)&~3) - nbytes));
220	}
221	/* avoid integer overflow */
222	if (i > INT_MAX - 1) {
223	    goto cleanpd;
224	}
225    }
226    *info = fhdr;
227    *count = i;
228    *pprops = pi;
229    *offsets = po;
230    *prop_data = pd;
231    SyncHandle();
232    return flist;
233
234/* Error cleanup for when we're partway through filling in item #i in arrays */
235cleanpd:
236    FSfree(pd[i]);
237cleanpo:
238    FSfree(po[i]);
239cleanpi:
240    FSfree(pi[i]);
241cleanflist:
242    FSfree(flist[i]);
243cleanfhdr:
244    FSfree(fhdr[i]);
245/* Error cleanup for all previously filled in items in the arrays */
246badmem:
247    for (int j = (i - 1); j >= 0; j--) {
248	FSfree(pi[j]);
249	FSfree(po[j]);
250	FSfree(pd[j]);
251	FSfree(flist[j]);
252	FSfree(fhdr[j]);
253    }
254    FSfree(flist);
255    FSfree(fhdr);
256    FSfree(pi);
257    FSfree(po);
258    FSfree(pd);
259
260    if (eat_data) {
261	do {
262	    fsPropInfo  ti;
263
264	    _FSEatData(svr, (reply.nameLength + 3) & ~3);
265	    _FSReadPad(svr, (char *) &ti, SIZEOF(fsPropInfo));
266	    _FSEatData(svr, (SIZEOF(fsPropOffset) * ti.num_offsets));
267	    _FSEatData(svr, ti.data_len);
268	} while (_FSReply(svr, (fsReply *) &reply,
269			  ((SIZEOF(fsListFontsWithXInfoReply)
270			    - SIZEOF(fsGenericReply)) >> 2), fsFalse)
271		 && (reply.nameLength != 0));
272    }
273    SyncHandle();
274    return (char **) NULL;
275}
276