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