1 /**************************************************************************/
2 /*                                                                        */
3 /* Copyright (c) 2001, 2010 NoMachine, http://www.nomachine.com/.         */
4 /*                                                                        */
5 /* NXCOMP, NX protocol compression and NX extensions to this software     */
6 /* are copyright of NoMachine. Redistribution and use of the present      */
7 /* software is allowed according to terms specified in the file LICENSE   */
8 /* which comes in the source distribution.                                */
9 /*                                                                        */
10 /* Check http://www.nomachine.com/licensing.html for applicability.       */
11 /*                                                                        */
12 /* NX and NoMachine are trademarks of Medialogic S.p.A.                   */
13 /*                                                                        */
14 /* All rights reserved.                                                   */
15 /*                                                                        */
16 /**************************************************************************/
17 
18 #include "PolyText8.h"
19 
20 #include "ClientCache.h"
21 
22 #include "EncodeBuffer.h"
23 #include "DecodeBuffer.h"
24 
25 //
26 // Set the verbosity level.
27 //
28 
29 #define PANIC
30 #define WARNING
31 #undef  TEST
32 #undef  DEBUG
33 #undef  DUMP
34 
35 //
36 // Here are the methods to handle messages' content.
37 //
38 
parseIdentity(Message * message,const unsigned char * buffer,unsigned int size,int bigEndian) const39 int PolyText8Store::parseIdentity(Message *message, const unsigned char *buffer,
40                                       unsigned int size, int bigEndian) const
41 {
42   PolyText8Message *polyText8 = (PolyText8Message *) message;
43 
44   //
45   // Here is the fingerprint.
46   //
47 
48   polyText8 -> drawable = GetULONG(buffer + 4, bigEndian);
49   polyText8 -> gcontext = GetULONG(buffer + 8, bigEndian);
50 
51   polyText8 -> x = GetUINT(buffer + 12, bigEndian);
52   polyText8 -> y = GetUINT(buffer + 14, bigEndian);
53 
54   //
55   // Clean up padding bytes.
56   //
57 
58   #ifdef DUMP
59 
60   DumpData(buffer, size);
61 
62   *logofs << "\n\n" << logofs_flush;
63 
64   #endif
65 
66   if ((int) size > dataOffset)
67   {
68     int length;
69     int current;
70     int delta;
71     int item;
72 
73     unsigned int nitem;
74 
75     unsigned char *pad = NULL;
76     unsigned char *end = NULL;
77 
78     delta = 1;
79     nitem = 0;
80 
81     #ifdef DUMP
82     *logofs << name() << " Size " << size << ".\n" << logofs_flush;
83     #endif
84 
85     //
86     // Data is a list of TextItem where element
87     // can be a string or a font shift.
88     //
89 
90     current = POLYTEXT8_DATA_OFFSET;
91     length  = POLYTEXT8_DATA_OFFSET;
92 
93     do
94     {
95       #ifdef DUMP
96       *logofs << name() << " Current " << current << ".\n" << logofs_flush;
97       #endif
98 
99       item = GetUINT(buffer + length , bigEndian);
100 
101       if (item < 255)
102       {
103         //
104         // Text element. Number represents
105         // the 'Length of string' field.
106         //
107 
108         length += (item + delta + 1);
109 
110 	nitem++;
111       }
112       else if (item == 255)
113       {
114         //
115         // Element is a font shift.
116         //
117 
118         length += 5;
119 
120         nitem++;
121       }
122 
123       #ifdef DUMP
124       *logofs << name() << " Item " << item << ".\n" << logofs_flush;
125       #endif
126 
127       current += length;
128     }
129     while(current < (int) size && item != 0);
130 
131 
132     #ifdef DUMP
133     *logofs << name() << " Final length " << length << ".\n" << logofs_flush;
134     #endif
135 
136     end = ((unsigned char *) buffer) + size;
137 
138     pad = ((unsigned char *) buffer) + length;
139 
140     for (; pad < end && nitem >= 1; pad++)
141     {
142       #ifdef DUMP
143       *logofs << name() << " Padding " << " .\n" << logofs_flush;
144       #endif
145 
146       *pad = 0;
147     }
148   }
149 
150   #ifdef DEBUG
151   *logofs << name() << ": Parsed Identity for message at " << this << ".\n" << logofs_flush;
152   #endif
153 
154   return 1;
155 }
156 
unparseIdentity(const Message * message,unsigned char * buffer,unsigned int size,int bigEndian) const157 int PolyText8Store::unparseIdentity(const Message *message, unsigned char *buffer,
158                                         unsigned int size, int bigEndian) const
159 {
160   PolyText8Message *polyText8 = (PolyText8Message *) message;
161 
162   //
163   // Fill all the message's fields.
164   //
165 
166   PutULONG(polyText8 -> drawable, buffer + 4, bigEndian);
167   PutULONG(polyText8 -> gcontext, buffer + 8, bigEndian);
168 
169   PutUINT(polyText8 -> x, buffer + 12, bigEndian);
170   PutUINT(polyText8 -> y, buffer + 14, bigEndian);
171 
172   #ifdef DEBUG
173   *logofs << name() << ": Unparsed identity for message at " << this << ".\n" << logofs_flush;
174   #endif
175 
176   return 1;
177 }
178 
dumpIdentity(const Message * message) const179 void PolyText8Store::dumpIdentity(const Message *message) const
180 {
181   #ifdef DUMP
182 
183   PolyText8Message *polyText8 = (PolyText8Message *) message;
184 
185   *logofs << name() << ": Identity drawable " << polyText8 -> drawable
186           << ", gcontext " << polyText8 -> gcontext << ", x " << polyText8 -> x
187           << ", y " << polyText8 -> y << ", size " << polyText8 -> size_
188           << ".\n";
189 
190   #endif
191 }
192 
identityChecksum(const Message * message,const unsigned char * buffer,unsigned int size,int bigEndian) const193 void PolyText8Store::identityChecksum(const Message *message, const unsigned char *buffer,
194                                           unsigned int size, int bigEndian) const
195 {
196 }
197 
updateIdentity(EncodeBuffer & encodeBuffer,const Message * message,const Message * cachedMessage,ChannelCache * channelCache) const198 void PolyText8Store::updateIdentity(EncodeBuffer &encodeBuffer, const Message *message,
199                                         const Message *cachedMessage,
200                                             ChannelCache *channelCache) const
201 {
202   PolyText8Message *polyText8       = (PolyText8Message *) message;
203   PolyText8Message *cachedPolyText8 = (PolyText8Message *) cachedMessage;
204 
205   ClientCache *clientCache = (ClientCache *) channelCache;
206 
207   #ifdef TEST
208   *logofs << name() << ": Encoding value " << polyText8 -> drawable
209           << " as " << "drawable" << " field.\n" << logofs_flush;
210   #endif
211 
212   encodeBuffer.encodeXidValue(polyText8 -> drawable, clientCache -> drawableCache);
213 
214   cachedPolyText8 -> drawable = polyText8 -> drawable;
215 
216   #ifdef TEST
217   *logofs << name() << ": Encoding value " << polyText8 -> gcontext
218           << " as " << "gcontext" << " field.\n" << logofs_flush;
219   #endif
220 
221   encodeBuffer.encodeXidValue(polyText8 -> gcontext, clientCache -> gcCache);
222 
223   cachedPolyText8 -> gcontext = polyText8 -> gcontext;
224 
225   #ifdef TEST
226   *logofs << name() << ": Encoding value " << polyText8 -> x
227           << " as " << "x" << " field.\n" << logofs_flush;
228   #endif
229 
230   unsigned short int diff_x = polyText8 -> x - cachedPolyText8 -> x;
231 
232   encodeBuffer.encodeCachedValue(diff_x, 16,
233                      clientCache -> polyTextCacheX);
234 
235   cachedPolyText8 -> x = polyText8 -> x;
236 
237   #ifdef TEST
238   *logofs << name() << ": Encoding value " << polyText8 -> y
239           << " as " << "y" << " field.\n" << logofs_flush;
240   #endif
241 
242   unsigned short int diff_y = polyText8 -> y - cachedPolyText8 -> y;
243 
244   encodeBuffer.encodeCachedValue(diff_y, 16,
245                      clientCache -> polyTextCacheY);
246 
247   cachedPolyText8 -> y = polyText8 -> y;
248 }
249 
updateIdentity(DecodeBuffer & decodeBuffer,const Message * message,ChannelCache * channelCache) const250 void PolyText8Store::updateIdentity(DecodeBuffer &decodeBuffer, const Message *message,
251                                         ChannelCache *channelCache) const
252 {
253   PolyText8Message *polyText8 = (PolyText8Message *) message;
254 
255   ClientCache *clientCache = (ClientCache *) channelCache;
256 
257   unsigned int value;
258 
259   decodeBuffer.decodeXidValue(value, clientCache -> drawableCache);
260 
261   polyText8 -> drawable = value;
262 
263   #ifdef DEBUG
264   *logofs << name() << ": Decoded value " << polyText8 -> drawable
265           << " as " << "drawable" << " field.\n" << logofs_flush;
266   #endif
267 
268   decodeBuffer.decodeXidValue(value, clientCache -> gcCache);
269 
270   polyText8 -> gcontext = value;
271 
272   #ifdef DEBUG
273   *logofs << name() << ": Decoded value " << polyText8 -> gcontext
274           << " as gcontext field.\n" << logofs_flush;
275   #endif
276 
277   decodeBuffer.decodeCachedValue(value, 16,
278                clientCache -> polyTextCacheX);
279 
280   polyText8 -> x += value;
281   polyText8 -> x &= 0xffff;
282 
283   #ifdef DEBUG
284   *logofs << name() << ": Decoded value " << polyText8 -> x
285           << " as x field.\n" << logofs_flush;
286   #endif
287 
288   decodeBuffer.decodeCachedValue(value, 16,
289                clientCache -> polyTextCacheY);
290 
291   polyText8 -> y += value;
292   polyText8 -> y &= 0xffff;
293 
294   #ifdef DEBUG
295   *logofs << name() << ": Decoded value " << polyText8 -> y
296           << " as y field.\n" << logofs_flush;
297   #endif
298 }
299