added libvnc/ with RealVNC compatibility fix
[presencevnc] / libvnc / libvncserver / tightvnc-filetransfer / handlefiletransferrequest.c
1 /*
2  * Copyright (c) 2005 Novell, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, contact Novell, Inc.
16  *
17  * To contact Novell about this file by physical or electronic mail,
18  * you may find current contact information at www.novell.com 
19  *
20  * Author               : Rohit Kumar
21  * Email ID     : rokumar@novell.com
22  * Date         : 14th July 2005
23  */
24  
25 #include <pwd.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include <pthread.h>
32 #include <sys/stat.h>
33 #include <sys/types.h>
34 #include <limits.h>
35
36 #include <rfb/rfb.h>
37 #include "rfbtightproto.h"
38 #include "filetransfermsg.h"
39 #include "handlefiletransferrequest.h"
40
41
42 pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER;
43
44 rfbBool fileTransferEnabled = TRUE;
45 rfbBool fileTransferInitted = FALSE;
46 char ftproot[PATH_MAX];
47
48
49 /******************************************************************************
50  * File Transfer Init methods. These methods are called for initializating 
51  * File Transfer and setting ftproot.
52  ******************************************************************************/
53  
54 void InitFileTransfer();
55 int SetFtpRoot(char* path);
56 char* GetHomeDir(uid_t uid);
57 void FreeHomeDir(char *homedir);
58
59 /*
60  * InitFileTransfer method is called before parsing the command-line options 
61  * for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc
62  * server. In case of error ftproot is set to '\0' char.
63  */
64  
65 void
66 InitFileTransfer()
67 {
68         char* userHome = NULL;
69         uid_t uid = geteuid();
70
71         if(fileTransferInitted)
72                 return;
73
74         rfbLog("tightvnc-filetransfer/InitFileTransfer\n");
75         
76         memset(ftproot, 0, sizeof(ftproot));
77         
78         userHome = GetHomeDir(uid);
79
80         if((userHome != NULL) && (strlen(userHome) != 0)) {
81                 SetFtpRoot(userHome);
82                 FreeHomeDir(userHome);
83         }
84         
85         fileTransferEnabled = TRUE;
86         fileTransferInitted = TRUE;
87 }
88
89 #ifndef __GNUC__
90 #define __FUNCTION__ "unknown"
91 #endif
92
93 /*
94  *  This method is called from InitFileTransfer method and
95  *  if the command line option for ftproot is provided.
96  */
97 int
98 SetFtpRoot(char* path)
99 {
100         struct stat stat_buf;
101         DIR* dir = NULL;
102
103         rfbLog("tightvnc-filetransfer/SetFtpRoot\n");
104         
105         if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) {
106                 rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot"
107                                 " not changed\n", __FILE__, __FUNCTION__);
108                 return FALSE;
109         }
110
111         if(stat(path, &stat_buf) < 0) {
112                 rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n", 
113                                 __FILE__, __FUNCTION__, path);
114                 return FALSE;
115         }
116
117         if(S_ISDIR(stat_buf.st_mode) == 0) {
118                 rfbLog("File [%s]: Method [%s]: path specified is not a directory\n",
119                                 __FILE__, __FUNCTION__);
120                 return FALSE;           
121         }
122
123         if((dir = opendir(path)) == NULL) {
124                 rfbLog("File [%s]: Method [%s]: Not able to open the directory\n",
125                                 __FILE__, __FUNCTION__);
126                 return FALSE;                   
127         }
128         else {
129                 closedir(dir);
130                 dir = NULL;
131         }
132         
133         
134         memset(ftproot, 0, PATH_MAX);
135         if(path[strlen(path)-1] == '/') {
136                 memcpy(ftproot, path, strlen(path)-1);  
137         }
138         else    
139                 memcpy(ftproot, path, strlen(path));    
140
141         
142         return TRUE;
143 }
144
145
146 /*
147  * Get the home directory for the user name
148  * param: username - name of the user for whom the home directory is required.
149  * returns: returns the home directory for the user, or null in case the entry 
150  * is not found or any error. The returned string must be freed by calling the 
151  * freehomedir function.
152 */
153 char* 
154 GetHomeDir(uid_t uid)
155 {
156         struct passwd *pwEnt = NULL;
157         char *homedir = NULL;
158
159         pwEnt = getpwuid (uid);
160         if (pwEnt == NULL)
161                 return NULL;
162
163         if(pwEnt->pw_dir != NULL) {
164                 homedir = strdup (pwEnt->pw_dir);
165         }
166
167         return homedir;
168 }
169
170
171 /*
172  * Free the home directory allocated by a previous call to retrieve the home 
173  * directory. param: homedir - the string returned by a previous call to 
174  * retrieve home directory for a user.
175  */
176 void 
177 FreeHomeDir(char *homedir)
178 {
179     free (homedir);
180 }
181
182
183 /******************************************************************************
184  * General methods.
185  ******************************************************************************/
186  
187 /*
188  * When the console sends the File Transfer Request, it sends the file path with
189  * ftproot as "/". So on Agent, to get the absolute file path we need to prepend
190  * the ftproot to it.
191  */
192 char*
193 ConvertPath(char* path)
194 {
195         char p[PATH_MAX];
196         memset(p, 0, PATH_MAX);
197         
198         if( (path == NULL) ||
199                 (strlen(path) == 0) ||
200                 (strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) {
201
202                 rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n",
203                                 __FILE__, __FUNCTION__);
204                 return NULL;
205         }
206
207         memcpy(p, path, strlen(path));
208         memset(path, 0, PATH_MAX);
209         sprintf(path, "%s%s", ftproot, p);
210
211         return path;
212 }
213
214
215 void
216 EnableFileTransfer(rfbBool enable)
217 {
218         fileTransferEnabled = enable;
219 }
220
221
222 rfbBool 
223 IsFileTransferEnabled()
224 {
225         return fileTransferEnabled;
226 }
227
228
229 char*
230 GetFtpRoot()
231 {
232         return ftproot;
233 }
234
235
236 /******************************************************************************
237  * Methods to Handle File List Request.
238  ******************************************************************************/
239  
240 /*
241  *  HandleFileListRequest method is called when the server receives 
242  *  FileListRequest. In case of success a file list is sent to the client.
243  *  For File List Request there is no failure reason sent.So here in case of any
244  *  "unexpected" error no information will be sent. As these conditions should 
245  *  never come. Lets hope it never arrives :)
246  *  In case of dir open failure an empty list will be sent, just the header of 
247  *  the message filled up. So on console you will get an Empty listing. 
248  */
249 void
250 HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data)
251 {
252         rfbClientToServerTightMsg msg;
253         int n = 0;
254         char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
255         FileTransferMsg fileListMsg;
256
257         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
258         memset(path, 0, PATH_MAX);
259         memset(&fileListMsg, 0, sizeof(FileTransferMsg));
260
261         if(cl == NULL) {
262                 rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", 
263                                 __FILE__, __FUNCTION__);
264                 return;
265         }
266
267         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) {
268                 
269                 if (n < 0)
270                         rfbLog("File [%s]: Method [%s]: Socket error while reading dir name"
271                                         " length\n", __FILE__, __FUNCTION__);
272                 
273             rfbCloseClient(cl);
274             return;
275         }
276         
277         msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize);
278         if ((msg.flr.dirNameSize == 0) ||
279                 (msg.flr.dirNameSize > (PATH_MAX - 1))) {
280                 
281                 rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is "
282                                 "greater that PATH_MAX\n", __FILE__, __FUNCTION__);
283
284                 return;         
285         }
286         
287         if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) {
288                 
289                 if (n < 0)
290                         rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n", 
291                                                         __FILE__, __FUNCTION__);
292                 
293             rfbCloseClient(cl);
294             return;
295         }
296
297         if(ConvertPath(path) == NULL) {
298
299                 /* The execution should never reach here */
300         rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", 
301                         __FILE__, __FUNCTION__);
302         return;
303         }
304         
305     fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags));
306
307     if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) {
308
309         rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is "
310                 "of Zero length\n",     __FILE__, __FUNCTION__);
311         return;
312         }       
313
314     rfbWriteExact(cl, fileListMsg.data, fileListMsg.length); 
315
316     FreeFileTransferMsg(fileListMsg);
317 }
318
319
320 /******************************************************************************
321  * Methods to Handle File Download Request.
322  ******************************************************************************/
323
324 void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize);
325 void SendFileDownloadLengthErrMsg(rfbClientPtr cl);
326 void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data);
327 #ifdef TODO
328 void HandleFileDownloadRequest(rfbClientPtr cl);
329 void SendFileDownloadErrMsg(rfbClientPtr cl);
330 void* RunFileDownloadThread(void* client);
331 #endif
332
333 /*
334  * HandleFileDownloadRequest method is called when the server receives 
335  * rfbFileDownload request message.
336  */
337 void
338 HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
339 {
340         int n = 0;
341         char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
342         rfbClientToServerTightMsg msg;
343
344         memset(path, 0, sizeof(path));
345         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
346         
347         if(cl == NULL) {
348                 
349                 rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n",
350                                 __FILE__, __FUNCTION__);
351                 return;
352         }
353
354         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) {
355                 
356                 if (n < 0)
357                         rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
358                                         __FILE__, __FUNCTION__);
359                 
360             rfbCloseClient(cl);
361             return;
362         }
363
364         msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize);
365         msg.fdr.position = Swap16IfLE(msg.fdr.position);
366
367         if ((msg.fdr.fNameSize == 0) ||
368                 (msg.fdr.fNameSize > (PATH_MAX - 1))) {
369                 
370                 rfbLog("File [%s]: Method [%s]: Error: path length is greater than"
371                                 " PATH_MAX\n", __FILE__, __FUNCTION__);
372                 
373                 HandleFileDownloadLengthError(cl, msg.fdr.fNameSize);
374                 return;
375         }
376
377         if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) {
378                 
379                 if (n < 0)
380                         rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n",
381                                                         __FILE__, __FUNCTION__);
382                 
383             rfbCloseClient(cl);
384             return;
385         }
386         rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0';
387
388         if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) {
389
390         rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL",
391                         __FILE__, __FUNCTION__);
392
393                  
394                  /* This condition can come only if the file path is greater than 
395                     PATH_MAX. So sending file path length error msg back to client. 
396                  */
397
398         SendFileDownloadLengthErrMsg(cl);
399         return;
400         }
401
402         HandleFileDownload(cl, rtcp);
403
404 }
405
406
407 void
408 HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize)
409 {
410         char *path = NULL;
411         int n = 0;
412         
413         if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
414                 rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", 
415                                 __FILE__, __FUNCTION__);
416                 return;
417         }
418         if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
419                 
420                 if (n < 0)
421                         rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", 
422                                                         __FILE__, __FUNCTION__);
423                 
424             rfbCloseClient(cl);
425
426             if(path != NULL) {
427                         free(path);
428                         path = NULL;
429                 }
430             
431             return;
432         }
433
434     if(path != NULL) {
435                 free(path);
436                 path = NULL;
437         }
438     
439         SendFileDownloadLengthErrMsg(cl);
440 }
441
442
443 void
444 SendFileDownloadLengthErrMsg(rfbClientPtr cl)
445 {
446         FileTransferMsg fileDownloadErrMsg;
447         
448         memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg));
449
450         fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg();
451
452         if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) {
453                 rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg "
454                                 "is null\n", __FILE__, __FUNCTION__);
455                 return;
456         }
457
458         rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length);
459
460         FreeFileTransferMsg(fileDownloadErrMsg);
461 }
462
463 extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl);
464
465 void*
466 RunFileDownloadThread(void* client)
467 {
468         rfbClientPtr cl = (rfbClientPtr) client;
469         rfbTightClientPtr rtcp = rfbGetTightClientData(cl);
470         FileTransferMsg fileDownloadMsg;
471
472         if(rtcp == NULL)
473                 return NULL;
474
475         memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
476         do {
477                 pthread_mutex_lock(&fileDownloadMutex);
478                 fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp);
479                 pthread_mutex_unlock(&fileDownloadMutex);
480                 
481                 if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
482                         if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0)  {
483                                 rfbLog("File [%s]: Method [%s]: Error while writing to socket \n"
484                                                 , __FILE__, __FUNCTION__);
485
486                                 if(cl != NULL) {
487                                 rfbCloseClient(cl);
488                                 CloseUndoneFileTransfer(cl, rtcp);
489                                 }
490                                 
491                                 FreeFileTransferMsg(fileDownloadMsg);
492                                 return NULL;
493                         }
494                         FreeFileTransferMsg(fileDownloadMsg);
495                 }
496         } while(rtcp->rcft.rcfd.downloadInProgress == TRUE);
497         return NULL;
498 }
499
500
501 void
502 HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp)
503 {
504         pthread_t fileDownloadThread;
505         FileTransferMsg fileDownloadMsg;
506         
507         memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg));
508         fileDownloadMsg = ChkFileDownloadErr(cl, rtcp);
509         if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) {
510                 rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length);
511                 FreeFileTransferMsg(fileDownloadMsg);
512                 return;
513         }
514         rtcp->rcft.rcfd.downloadInProgress = FALSE;
515         rtcp->rcft.rcfd.downloadFD = -1;
516
517         if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*) 
518         cl) != 0) {
519                 FileTransferMsg ftm = GetFileDownLoadErrMsg();
520                 
521                 rfbLog("File [%s]: Method [%s]: Download thread creation failed\n",
522                                 __FILE__, __FUNCTION__);
523                 
524                 if((ftm.data != NULL) && (ftm.length != 0)) {
525                         rfbWriteExact(cl, ftm.data, ftm.length);
526                         FreeFileTransferMsg(ftm);
527                         return;
528                 }
529                                 
530         }
531         
532 }
533
534
535 /******************************************************************************
536  * Methods to Handle File Download Cancel Request.
537  ******************************************************************************/
538
539  
540 void
541 HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
542 {
543         int n = 0;
544         char *reason = NULL;
545         rfbClientToServerTightMsg msg;
546
547         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
548         
549         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) {
550                 
551                 if (n < 0)
552                         rfbLog("File [%s]: Method [%s]: Error while reading "
553                                         "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
554                 
555             rfbCloseClient(cl);
556             return;
557         }
558
559         msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen);
560
561         if(msg.fdc.reasonLen == 0) {
562                 rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
563                                 __FILE__, __FUNCTION__);
564                 return;
565         }
566         
567         reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char));
568         if(reason == NULL) {
569                 rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n", 
570                                 __FILE__, __FUNCTION__);
571                 return;
572         }
573
574         if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) {
575                 
576                 if (n < 0)
577                         rfbLog("File [%s]: Method [%s]: Error while reading "
578                                         "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__);
579                 
580             rfbCloseClient(cl);
581         }
582
583         rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:"
584                                         " reason <%s>\n", __FILE__, __FUNCTION__, reason);
585         
586         pthread_mutex_lock(&fileDownloadMutex);
587         CloseUndoneFileTransfer(cl, rtcp);
588         pthread_mutex_unlock(&fileDownloadMutex);
589         
590         if(reason != NULL) {
591                 free(reason);
592                 reason = NULL;
593         }
594
595 }
596
597
598 /******************************************************************************
599  * Methods to Handle File upload request
600  ******************************************************************************/
601
602 #ifdef TODO
603 void HandleFileUploadRequest(rfbClientPtr cl);
604 #endif
605 void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data);
606 void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize);
607 void SendFileUploadLengthErrMsg(rfbClientPtr cl);
608
609
610 void
611 HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
612 {
613         int n = 0;
614         char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */
615         rfbClientToServerTightMsg msg;
616
617         memset(path, 0, PATH_MAX);
618         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
619         
620         if(cl == NULL) {
621                 rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
622                                 __FILE__, __FUNCTION__);
623                 return;
624         }
625         
626         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) {
627                 
628                 if (n < 0)
629                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
630                                         __FILE__, __FUNCTION__);
631                 
632             rfbCloseClient(cl);
633             return;
634         }
635
636         msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize);
637         msg.fupr.position = Swap16IfLE(msg.fupr.position);
638
639         if ((msg.fupr.fNameSize == 0) ||
640                 (msg.fupr.fNameSize > (PATH_MAX - 1))) {
641                 
642                 rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n",
643                                 __FILE__, __FUNCTION__);
644                 HandleFileUploadLengthError(cl, msg.fupr.fNameSize);
645                 return;
646         }
647
648         if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) {
649                 
650                 if (n < 0)
651                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n"
652                                         __FILE__, __FUNCTION__);
653                 
654             rfbCloseClient(cl);
655             return;
656         }
657         rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0';
658         
659         if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) {
660         rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
661                         __FILE__, __FUNCTION__);
662
663         /* This may come if the path length exceeds PATH_MAX.
664            So sending path length error to client
665          */
666          SendFileUploadLengthErrMsg(cl);
667         return;
668         }
669
670         HandleFileUpload(cl, rtcp);
671 }
672
673
674 void
675 HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize)
676 {
677         char *path = NULL;
678         int n = 0;
679         
680         if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) {
681                 rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", 
682                                 __FILE__, __FUNCTION__);
683                 return;
684         }
685         if((n = rfbReadExact(cl, path, fNameSize)) <= 0) {
686                 
687                 if (n < 0)
688                         rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", 
689                                                         __FILE__, __FUNCTION__);
690                 
691             rfbCloseClient(cl);
692
693             if(path != NULL) {
694                         free(path);
695                         path = NULL;
696                 }
697             
698             return;
699         }
700
701         rfbLog("File [%s]: Method [%s]: File Upload Length Error occured"
702                         "file path requested is <%s>\n", __FILE__, __FUNCTION__, path);
703
704     if(path != NULL) {
705                 free(path);
706                 path = NULL;
707         }
708
709     SendFileUploadLengthErrMsg(cl);
710 }
711
712 void
713 SendFileUploadLengthErrMsg(rfbClientPtr cl)
714 {
715
716         FileTransferMsg fileUploadErrMsg;
717         
718         memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
719         fileUploadErrMsg = GetFileUploadLengthErrResponseMsg();
720
721         if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) {
722                 rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n",
723                                 __FILE__, __FUNCTION__);
724                 return;
725         }
726
727         rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
728         FreeFileTransferMsg(fileUploadErrMsg);
729 }
730
731 void
732 HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp)
733 {
734         FileTransferMsg fileUploadErrMsg;
735
736         memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg));
737         
738         rtcp->rcft.rcfu.uploadInProgress = FALSE;
739         rtcp->rcft.rcfu.uploadFD = -1;
740
741         fileUploadErrMsg = ChkFileUploadErr(cl, rtcp);
742         if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) {
743                 rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length);
744                 FreeFileTransferMsg(fileUploadErrMsg);
745         }
746 }
747
748
749 /******************************************************************************
750  * Methods to Handle File Upload Data Request
751  *****************************************************************************/
752
753 void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf);
754
755
756 void
757 HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
758 {
759         int n = 0;
760         char* pBuf = NULL;
761         rfbClientToServerTightMsg msg;
762
763         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
764         
765         if(cl == NULL) {
766                 rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
767                                 __FILE__, __FUNCTION__);
768                 return;
769         }
770
771         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) {
772                 
773                 if (n < 0)
774                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
775                                         __FILE__, __FUNCTION__);
776                 
777             rfbCloseClient(cl);
778             return;
779         }
780
781         msg.fud.realSize = Swap16IfLE(msg.fud.realSize);
782         msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize);
783         if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) {
784                 if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned 
785                 long))) <= 0) {
786                         
787                         if (n < 0)
788                                 rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
789                                                 __FILE__, __FUNCTION__);
790                         
791                     rfbCloseClient(cl);
792                     return;
793                 }
794
795                 FileUpdateComplete(cl, rtcp);
796                 return;
797         }
798
799         pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char));
800         if(pBuf == NULL) {
801                 rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
802                 return;
803         }
804         if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) {
805                 
806                 if (n < 0)
807                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n",
808                                         __FILE__, __FUNCTION__);
809                 
810             rfbCloseClient(cl);
811
812             if(pBuf != NULL) {
813                 free(pBuf);
814                 pBuf = NULL;
815                 }
816             
817             return;
818         }       
819         if(msg.fud.compressedLevel != 0) {
820                 FileTransferMsg ftm;
821                 memset(&ftm, 0, sizeof(FileTransferMsg));
822                 
823                 ftm = GetFileUploadCompressedLevelErrMsg();
824
825                 if((ftm.data != NULL) && (ftm.length != 0)) {
826                         rfbWriteExact(cl, ftm.data, ftm.length);
827                         FreeFileTransferMsg(ftm);
828                 }
829
830                 CloseUndoneFileTransfer(cl, rtcp);
831
832             if(pBuf != NULL) {
833                 free(pBuf);
834                 pBuf = NULL;
835                 }
836                 
837                 return;
838         }
839
840         rtcp->rcft.rcfu.fSize = msg.fud.compressedSize;
841         
842         HandleFileUploadWrite(cl, rtcp, pBuf);
843
844     if(pBuf != NULL) {
845         free(pBuf);
846         pBuf = NULL;
847         }
848
849 }
850
851
852 void
853 HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf)
854 {
855         FileTransferMsg ftm;
856         memset(&ftm, 0, sizeof(FileTransferMsg));
857
858         ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf);
859
860         if((ftm.data != NULL) && (ftm.length != 0)) {
861                 rfbWriteExact(cl, ftm.data, ftm.length);
862                 FreeFileTransferMsg(ftm);
863         }
864 }
865
866
867 /******************************************************************************
868  * Methods to Handle File Upload Failed Request.
869  ******************************************************************************/
870
871  
872 void 
873 HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
874 {
875         int n = 0;
876         char* reason = NULL;
877         rfbClientToServerTightMsg msg;
878
879         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
880         
881         if(cl == NULL) {
882                 rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
883                                 __FILE__, __FUNCTION__);
884                 return;
885         }
886         
887         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) {
888                 
889                 if (n < 0)
890                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
891                                         __FILE__, __FUNCTION__);
892                 
893             rfbCloseClient(cl);
894             return;
895         }
896
897         msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen);
898         if(msg.fuf.reasonLen  == 0) {
899                 rfbLog("File [%s]: Method [%s]: reason length received is Zero\n",
900                                 __FILE__, __FUNCTION__);
901                 return;
902         }
903
904
905         reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char));
906         if(reason == NULL) {
907                 rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__);
908                 return;         
909         }
910         
911         if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) {
912                 
913                 if (n < 0)
914                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
915                                         __FILE__, __FUNCTION__);
916                 
917             rfbCloseClient(cl);
918
919                 if(reason != NULL) {
920                         free(reason);
921                         reason = NULL;
922                 }
923
924             return;
925         }
926
927         rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:"
928                                 " reason <%s>\n", __FILE__, __FUNCTION__, reason);
929
930         CloseUndoneFileTransfer(cl, rtcp);
931
932         if(reason != NULL) {
933                 free(reason);
934                 reason = NULL;
935         }
936
937 }
938
939
940 /******************************************************************************
941  * Methods to Handle File Create Request.
942  ******************************************************************************/
943
944  
945 void 
946 HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp)
947 {
948         int n = 0;
949         char dirName[PATH_MAX];
950         rfbClientToServerTightMsg msg;
951
952         memset(dirName, 0, PATH_MAX);
953         memset(&msg, 0, sizeof(rfbClientToServerTightMsg));
954         
955         if(cl == NULL) {
956                 rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n",
957                                 __FILE__, __FUNCTION__);
958                 return;
959         }
960         
961         if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) {
962                 
963                 if (n < 0)
964                         rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n",
965                                         __FILE__, __FUNCTION__);
966                 
967             rfbCloseClient(cl);
968             return;
969         }
970
971         msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen);
972
973         /* TODO :: chk if the dNameLen is greater than PATH_MAX */      
974         
975         if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) {
976                 
977                 if (n < 0)
978                         rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n",
979                                         __FILE__, __FUNCTION__);
980                 
981             rfbCloseClient(cl);
982             return;
983         }
984
985         if(ConvertPath(dirName) == NULL) {
986         rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n",
987                         __FILE__, __FUNCTION__);
988
989         return;
990         }
991
992         CreateDirectory(dirName);
993 }