1 /***********************************************************
3 Copyright (c) 1987 X Consortium
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of the X Consortium shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from the X Consortium.
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
47 ******************************************************************/
48 /* $XConsortium: property.c /main/41 1996/12/22 12:33:58 rws $ */
49 /* $XFree86: xc/programs/Xserver/dix/property.c,v 3.5 1996/12/24 11:52:04 dawes Exp $ */
55 #include "windowstr.h"
56 #include "propertyst.h"
57 #include "dixstruct.h"
61 #define _SECURITY_SERVER
62 #include "extensions/security.h"
65 #if defined(LBX) || defined(LBX_COMPAT)
66 int fWriteToClient(client, len, buf)
71 return WriteToClient(client, len, buf);
75 /*****************************************************************
78 * ChangeProperty, DeleteProperty, GetProperties,
81 * Properties below to windows. A allocate slots each time
82 * a property is added. No fancy searching done.
84 *****************************************************************/
94 pProp = pWin->userProps;
97 ErrorF( "%x %x\n", pProp->propertyName, pProp->type);
98 ErrorF("property format: %d\n", pProp->format);
99 ErrorF("property data: \n");
100 for (j=0; j<(pProp->format/8)*pProp->size; j++)
101 ErrorF("%c\n", pProp->data[j]);
108 ProcRotateProperties(client)
112 REQUEST(xRotatePropertiesReq);
114 register Atom * atoms;
115 PropertyPtr * props; /* array of pointer */
119 REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
121 pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
122 SecurityWriteAccess);
127 atoms = (Atom *) & stuff[1];
128 props = (PropertyPtr *)ALLOCATE_LOCAL(stuff->nAtoms * sizeof(PropertyPtr));
131 for (i = 0; i < stuff->nAtoms; i++)
134 char action = SecurityCheckPropertyAccess(client, pWin, atoms[i],
135 SecurityReadAccess|SecurityWriteAccess);
137 if (!ValidAtom(atoms[i])
139 || (SecurityErrorOperation == action)
143 DEALLOCATE_LOCAL(props);
144 client->errorValue = atoms[i];
148 if (SecurityIgnoreOperation == action)
150 DEALLOCATE_LOCAL(props);
154 for (j = i + 1; j < stuff->nAtoms; j++)
155 if (atoms[j] == atoms[i])
157 DEALLOCATE_LOCAL(props);
160 pProp = wUserProps (pWin);
163 if (pProp->propertyName == atoms[i])
167 DEALLOCATE_LOCAL(props);
172 delta = stuff->nPositions;
174 /* If the rotation is a complete 360 degrees, then moving the properties
175 around and generating PropertyNotify events should be skipped. */
177 if ( (stuff->nAtoms != 0) && (abs(delta) % stuff->nAtoms) != 0 )
179 while (delta < 0) /* faster if abs value is small */
180 delta += stuff->nAtoms;
181 for (i = 0; i < stuff->nAtoms; i++)
183 /* Generate a PropertyNotify event for each property whose value
184 is changed in the order in which they appear in the request. */
186 event.u.u.type = PropertyNotify;
187 event.u.property.window = pWin->drawable.id;
188 event.u.property.state = PropertyNewValue;
189 event.u.property.atom = props[i]->propertyName;
190 event.u.property.time = currentTime.milliseconds;
191 DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
193 props[i]->propertyName = atoms[(i + delta) % stuff->nAtoms];
196 DEALLOCATE_LOCAL(props);
201 ProcChangeProperty(client)
210 REQUEST(xChangePropertyReq);
212 REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
214 format = stuff->format;
216 if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
217 (mode != PropModePrepend))
219 client->errorValue = mode;
222 if ((format != 8) && (format != 16) && (format != 32))
224 client->errorValue = format;
228 if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
230 sizeInBytes = format>>3;
231 totalSize = len * sizeInBytes;
232 REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
234 pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
235 SecurityWriteAccess);
238 if (!ValidAtom(stuff->property))
240 client->errorValue = stuff->property;
243 if (!ValidAtom(stuff->type))
245 client->errorValue = stuff->type;
250 switch (SecurityCheckPropertyAccess(client, pWin, stuff->property,
251 SecurityWriteAccess))
253 case SecurityErrorOperation:
254 client->errorValue = stuff->property;
256 case SecurityIgnoreOperation:
262 err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type,
263 (int)format, (int)mode, len, TRUE, (pointer)&stuff[1], TRUE, NULL);
265 err = ChangeWindowProperty(pWin, stuff->property, stuff->type, (int)format,
266 (int)mode, len, (pointer)&stuff[1], TRUE);
271 return client->noClientException;
275 ChangeWindowProperty(pWin, property, type, format, mode, len, value, sendevent)
284 return LbxChangeWindowProperty(NULL, pWin, property, type,
285 format, mode, len, TRUE, value,
294 sizeInBytes = format>>3;
295 totalSize = len * sizeInBytes;
297 /* first see if property already exists */
299 pProp = wUserProps (pWin);
302 if (pProp->propertyName == property)
306 if (!pProp) /* just add to list */
308 if (!pWin->optional && !MakeWindowOptional (pWin))
310 pProp = (PropertyPtr)xalloc(sizeof(PropertyRec));
313 data = (pointer)xalloc(totalSize);
319 pProp->propertyName = property;
321 pProp->format = format;
324 memmove((char *)data, (char *)value, totalSize);
326 pProp->next = pWin->optional->userProps;
327 pWin->optional->userProps = pProp;
331 /* To append or prepend to a property the request format and type
332 must match those of the already defined property. The
333 existing format and type are irrelevant when using the mode
334 "PropModeReplace" since they will be written over. */
336 if ((format != pProp->format) && (mode != PropModeReplace))
338 if ((pProp->type != type) && (mode != PropModeReplace))
340 if (mode == PropModeReplace)
342 if (totalSize != pProp->size * (pProp->format >> 3))
344 data = (pointer)xrealloc(pProp->data, totalSize);
350 memmove((char *)pProp->data, (char *)value, totalSize);
353 pProp->format = format;
359 else if (mode == PropModeAppend)
361 data = (pointer)xrealloc(pProp->data,
362 sizeInBytes * (len + pProp->size));
366 memmove(&((char *)data)[pProp->size * sizeInBytes],
371 else if (mode == PropModePrepend)
373 data = (pointer)xalloc(sizeInBytes * (len + pProp->size));
376 memmove(&((char *)data)[totalSize], (char *)pProp->data,
377 (int)(pProp->size * sizeInBytes));
378 memmove((char *)data, (char *)value, totalSize);
386 event.u.u.type = PropertyNotify;
387 event.u.property.window = pWin->drawable.id;
388 event.u.property.state = PropertyNewValue;
389 event.u.property.atom = pProp->propertyName;
390 event.u.property.time = currentTime.milliseconds;
391 DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
394 /* Addition for RFB X server */
395 if (pWin->parent == NullWindow) {
396 extern void rfbRootPropertyChange();
397 rfbRootPropertyChange(pProp);
405 DeleteProperty(pWin, propName)
409 PropertyPtr pProp, prevProp;
412 if (!(pProp = wUserProps (pWin)))
414 prevProp = (PropertyPtr)NULL;
417 if (pProp->propertyName == propName)
424 if (prevProp == (PropertyPtr)NULL) /* takes care of head */
426 if (!(pWin->optional->userProps = pProp->next))
427 CheckWindowOptionalNeed (pWin);
431 prevProp->next = pProp->next;
435 TagDeleteTag(pProp->tag_id);
437 event.u.u.type = PropertyNotify;
438 event.u.property.window = pWin->drawable.id;
439 event.u.property.state = PropertyDelete;
440 event.u.property.atom = pProp->propertyName;
441 event.u.property.time = currentTime.milliseconds;
442 DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
450 DeleteAllWindowProperties(pWin)
453 PropertyPtr pProp, pNextProp;
456 pProp = wUserProps (pWin);
461 TagDeleteTag(pProp->tag_id);
463 event.u.u.type = PropertyNotify;
464 event.u.property.window = pWin->drawable.id;
465 event.u.property.state = PropertyDelete;
466 event.u.property.atom = pProp->propertyName;
467 event.u.property.time = currentTime.milliseconds;
468 DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
469 pNextProp = pProp->next;
477 NullPropertyReply(client, propertyType, format, reply)
481 xGetPropertyReply *reply;
485 reply->bytesAfter = 0;
486 reply->propertyType = propertyType;
487 reply->format = format;
488 WriteReplyToClient(client, sizeof(xGenericReply), reply);
489 return(client->noClientException);
494 * If type Any is specified, returns the property from the specified
495 * window regardless of its type. If a type is specified, returns the
496 * property only if its type equals the specified type.
497 * If delete is True and a property is returned, the property is also
498 * deleted from the window and a PropertyNotify event is generated on the
503 ProcGetProperty(client)
506 PropertyPtr pProp, prevProp;
507 unsigned long n, len, ind;
509 xGetPropertyReply reply;
510 REQUEST(xGetPropertyReq);
512 REQUEST_SIZE_MATCH(xGetPropertyReq);
515 pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
520 if (!ValidAtom(stuff->property))
522 client->errorValue = stuff->property;
525 if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
527 client->errorValue = stuff->delete;
530 if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
532 client->errorValue = stuff->type;
536 pProp = wUserProps (pWin);
537 prevProp = (PropertyPtr)NULL;
540 if (pProp->propertyName == stuff->property)
546 reply.type = X_Reply;
547 reply.sequenceNumber = client->sequence;
549 return NullPropertyReply(client, None, 0, &reply);
553 Mask access_mode = SecurityReadAccess;
556 access_mode |= SecurityDestroyAccess;
557 switch(SecurityCheckPropertyAccess(client, pWin, stuff->property,
560 case SecurityErrorOperation:
561 client->errorValue = stuff->property;
563 case SecurityIgnoreOperation:
564 return NullPropertyReply(client, pProp->type, pProp->format,
569 /* If the request type and actual type don't match. Return the
570 property information, but not the data. */
572 if (((stuff->type != pProp->type) &&
573 (stuff->type != AnyPropertyType))
576 reply.bytesAfter = pProp->size;
577 reply.format = pProp->format;
580 reply.propertyType = pProp->type;
581 WriteReplyToClient(client, sizeof(xGenericReply), &reply);
585 /* make sure we have the current value */
586 if (pProp->tag_id && pProp->owner_pid) {
587 LbxStallPropRequest(client, pProp);
588 return client->noClientException;
593 * Return type, format, value to client
595 n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
596 ind = stuff->longOffset << 2;
598 /* If longOffset is invalid such that it causes "len" to
599 be negative, it's a value error. */
603 client->errorValue = stuff->longOffset;
607 len = min(n - ind, 4 * stuff->longLength);
609 reply.bytesAfter = n - (ind + len);
610 reply.format = pProp->format;
611 reply.length = (len + 3) >> 2;
612 reply.nItems = len / (pProp->format / 8 );
613 reply.propertyType = pProp->type;
615 if (stuff->delete && (reply.bytesAfter == 0))
616 { /* send the event */
619 event.u.u.type = PropertyNotify;
620 event.u.property.window = pWin->drawable.id;
621 event.u.property.state = PropertyDelete;
622 event.u.property.atom = pProp->propertyName;
623 event.u.property.time = currentTime.milliseconds;
624 DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
627 WriteReplyToClient(client, sizeof(xGenericReply), &reply);
630 switch (reply.format) {
631 case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
632 case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
633 default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
635 WriteSwappedDataToClient(client, len,
636 (char *)pProp->data + ind);
639 if (stuff->delete && (reply.bytesAfter == 0))
640 { /* delete the Property */
643 TagDeleteTag(pProp->tag_id);
645 if (prevProp == (PropertyPtr)NULL) /* takes care of head */
647 if (!(pWin->optional->userProps = pProp->next))
648 CheckWindowOptionalNeed (pWin);
651 prevProp->next = pProp->next;
655 return(client->noClientException);
659 ProcListProperties(client)
662 Atom *pAtoms, *temppAtoms;
663 xListPropertiesReply xlpr;
667 REQUEST(xResourceReq);
669 REQUEST_SIZE_MATCH(xResourceReq);
670 pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client,
675 pProp = wUserProps (pWin);
682 if(!(pAtoms = (Atom *)ALLOCATE_LOCAL(numProps * sizeof(Atom))))
686 xlpr.nProperties = numProps;
687 xlpr.length = (numProps * sizeof(Atom)) >> 2;
688 xlpr.sequenceNumber = client->sequence;
689 pProp = wUserProps (pWin);
693 *temppAtoms++ = pProp->propertyName;
696 WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
699 client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
700 WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
701 DEALLOCATE_LOCAL(pAtoms);
703 return(client->noClientException);
707 ProcDeleteProperty(client)
708 register ClientPtr client;
711 REQUEST(xDeletePropertyReq);
714 REQUEST_SIZE_MATCH(xDeletePropertyReq);
716 pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
717 SecurityWriteAccess);
720 if (!ValidAtom(stuff->property))
722 client->errorValue = stuff->property;
727 switch(SecurityCheckPropertyAccess(client, pWin, stuff->property,
728 SecurityDestroyAccess))
730 case SecurityErrorOperation:
731 client->errorValue = stuff->property;
733 case SecurityIgnoreOperation:
738 result = DeleteProperty(pWin, stuff->property);
739 if (client->noClientException != Success)
740 return(client->noClientException);