hti/PC_Tools/HTIGateway/ServicePlugins/HtiFtp/HtiFtp.cpp
branchRCL_3
changeset 59 8ad140f3dd41
parent 0 a03f92240627
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hti/PC_Tools/HTIGateway/ServicePlugins/HtiFtp/HtiFtp.cpp	Wed Oct 13 16:17:58 2010 +0300
@@ -0,0 +1,790 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+* 
+* Description:
+*/
+#include "HtiFtpH.h"
+
+#include "HtiPlugin.h"
+#include <string.h>
+
+#include "HtiSoapHandlerInterface.h"
+
+const unsigned char CMD_FTP_STOR	    = 0x03;
+const unsigned char CMD_FTP_RETR	    = 0x05;
+const unsigned char CMD_FTP_LIST	    = 0x07;
+const unsigned char CMD_FTP_LISTDIR	    = 0x11;
+const unsigned char CMD_FTP_LISTSIZE    = 0x13;
+const unsigned char CMD_FTP_LISTDRIVES  = 0x15;
+const unsigned char CMD_FTP_MKD		    = 0x09;
+const unsigned char CMD_FTP_RMD	    	= 0x0B;
+const unsigned char CMD_FTP_DELE	    = 0x0D;
+const unsigned char CMD_FTP_CANCEL	    = 0x0E;
+const unsigned char CMD_FTP_FILESIZE    = 0x0F;
+
+const unsigned char CMD_FTP_SETFORCE	= 0x20;
+const unsigned char CMD_FTP_CHECKSUM	= 0x30;
+const unsigned char CMD_FTP_CHECKSUM_U	= 0x31;
+const unsigned char CMD_FTP_FORMAT      = 0x40;
+
+const unsigned char CMD_FTP_OK		= 0xF0;
+const unsigned char CONTROL_PRIORITY = 2;
+
+const int MAX_HTI_MSG_SIZE = 8192;
+
+char fileMimeType[] = "application/octet-stream"; //??
+
+const static int g_ftpHtiTimeoutControl = 10000;
+const static int g_ftpHtiTimeoutData = 60*60000;
+
+int sendHtiMessage(struct soap *soap,
+				   const char cmd,
+				   const wchar_t* arg )
+{
+	int resultCode = SOAP_OK;
+	
+	int textLen = 0;
+	int bodyLen = 0;
+	if ( arg )
+	{
+		textLen = (int)wcslen( arg );
+		if ( textLen > 0xFF )
+		{
+			soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+			resultCode = SOAP_FAULT;
+			return resultCode;
+		}
+		bodyLen = 2*textLen + 2;
+	}
+	else
+	{
+        bodyLen = 1;
+	}
+
+	BYTE* msgBody = new BYTE[ bodyLen ];
+	msgBody[0] = cmd;
+
+	if ( arg )
+	{
+		msgBody[1] = textLen;
+		memcpy( msgBody + 2, arg, 2*textLen );
+	}
+
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	handler->SendHtiMessage(HTI_UID, msgBody, bodyLen, CONTROL_PRIORITY );
+
+	delete[] msgBody;
+	return resultCode;
+}
+
+int receiveFtpOk( struct soap *soap, DWORD waitTimeout )
+{
+	int resultCode = SOAP_OK;
+	
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	if ( handler->WaitForHtiMessage( waitTimeout ) )
+	{
+		if ( !handler->IsReceivedHtiError() )
+		{
+			DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+			BYTE* body = (BYTE*)(handler->ReceivedHtiMessageBody());
+
+			if ( ! ( bodySize == 1 && body[0] == CMD_FTP_OK ) )
+			{
+				soap->error = soap_receiver_fault(soap,
+												"Received invalid hti message", NULL);
+				resultCode = SOAP_FAULT;
+			}
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			resultCode = SOAP_FAULT;
+		}
+	}
+	else
+	{
+		soap->error = soap_receiver_fault(soap,
+										  "Failed receive hti message", NULL);
+		resultCode = SOAP_FAULT;
+	}
+	
+	return resultCode;
+}
+
+int sendHtiMessageAndReceiveOK(struct soap *soap,
+							   const char cmd,
+							   const wchar_t* arg )
+{
+	if ( arg == NULL )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+	int resultCode = sendHtiMessage( soap, cmd, arg );
+	if ( resultCode != SOAP_OK )
+	{
+		return resultCode;
+	}
+	
+	return receiveFtpOk(soap, g_ftpHtiTimeoutControl);
+}
+
+int sendHtiMessageAndReceiveStringArray(struct soap *soap,
+										const char cmd,
+										const wchar_t* arg,
+										struct ArrayOfStrings &array )
+{
+	if ( arg == NULL )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+
+	int resultCode = SOAP_OK;
+	resultCode = sendHtiMessage( soap, cmd, arg );
+	if ( resultCode != SOAP_OK )
+	{
+		return resultCode;
+	}
+	
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	if (handler->WaitForHtiMessage(g_ftpHtiTimeoutData) )
+	{
+		if ( !handler->IsReceivedHtiError() )
+		{
+            DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+			BYTE* body = (BYTE*)(handler->ReceivedHtiMessageBody());
+			//check that body size is valid
+			if ( bodySize > 0 )
+			{
+				//calculate number of elements
+				DWORD i = 0;
+				int numOfElements = 0;
+				while ( i < bodySize )
+				{
+                    ++numOfElements;
+					i += 2*body[i] + 1;
+				}
+
+				//printf("strings: %d\n", numOfElements);
+
+				if ( i != bodySize )
+				{
+					soap->error = soap_receiver_fault(soap,
+													"Invalid hti message", NULL);
+					resultCode = SOAP_FAULT;
+				}
+				else
+				{
+					array.__size = numOfElements;
+					array.__ptr = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)*array.__size );
+					int j;
+					for( j=0, i=0; j<array.__size; ++j, i += 2*body[i] + 1)
+					{
+						//printf("%d size=%d ", j, body[i]);
+						array.__ptr[j] = (wchar_t*)soap_malloc(soap, 2*body[i] + 2 );
+						memcpy(array.__ptr[j],
+								body + i + 1,
+								2*body[i] );
+						(array.__ptr[j])[body[i]] = 0; //null char
+						int strLen = (int)wcslen( array.__ptr[j] );
+
+						//wprintf(L">%S<\n", array.__ptr[j] );
+						//printf("\n");
+					}
+				}
+			}
+			else
+			{
+				array.__size = 0;
+				array.__ptr = 0;
+			}
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			resultCode = SOAP_FAULT;
+		}
+	}
+	else
+	{
+		soap->error = soap_receiver_fault(soap,
+										  "Failed receive hti message", NULL);
+		resultCode = SOAP_FAULT;
+	}
+	
+	return resultCode;
+}
+
+int sendHtiMessageAndReceiveHtiFileInfoArray(struct soap *soap,
+										const char cmd,
+										const wchar_t* arg,
+										struct ArrayOfHtiFileInfos &array )
+{
+	if ( arg == NULL )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+
+	int resultCode = SOAP_OK;
+	resultCode = sendHtiMessage( soap, cmd, arg );
+	if ( resultCode != SOAP_OK )
+	{
+		return resultCode;
+	}
+	
+	HtiSoapHandlerInterface* handler =
+        static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	if (handler->WaitForHtiMessage(g_ftpHtiTimeoutData) )
+	{
+		if ( !handler->IsReceivedHtiError() )
+		{
+            DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+			BYTE* body = (BYTE*)(handler->ReceivedHtiMessageBody());
+			//check that body size is valid
+			if ( bodySize > 0 )
+			{
+				//calculate number of elements
+				DWORD i = 0;
+				int numOfElements = 0;
+				while ( i < bodySize )
+				{
+                    ++numOfElements;
+					i += 2*body[i] + 1 + 4;
+				}
+
+                if ( i != bodySize )
+				{
+					soap->error = soap_receiver_fault(soap,
+											"Invalid hti message", NULL);
+					resultCode = SOAP_FAULT;
+				}
+				else
+				{
+					array.__size = numOfElements;
+					array.__ptr = (ns1__HtiFileInfo*) soap_malloc(
+                            soap, sizeof(ns1__HtiFileInfo)*array.__size );
+					int j;
+					for( j=0, i=0; j<array.__size; ++j, i += 2*body[i] + 1 + 4)
+					{
+						array.__ptr[j].fileName =
+                            (wchar_t*)soap_malloc(soap, 2*body[i] + 2 );
+						memcpy(array.__ptr[j].fileName, body + i + 1, 2*body[i]);
+                        (array.__ptr[j].fileName)[body[i]] = 0; //null char
+                        // the file size bytes
+                        array.__ptr[j].fileSize = *(int*)(body + i + 2*body[i] + 1);
+                    }
+                }
+            }
+			else
+			{
+				array.__size = 0;
+				array.__ptr = 0;
+			}
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			resultCode = SOAP_FAULT;
+		}
+	}
+	else
+	{
+		soap->error = soap_receiver_fault(soap,
+										  "Failed receive hti message", NULL);
+		resultCode = SOAP_FAULT;
+	}
+
+    return resultCode;
+}
+
+int sendHtiMessageAndReceiveHtiDriveInfoArray(struct soap *soap,
+                                        const char cmd,
+                                        struct ArrayOfHtiDriveInfos &array )
+{
+	int resultCode = SOAP_OK;
+	resultCode = sendHtiMessage( soap, cmd, NULL );
+	if ( resultCode != SOAP_OK )
+	{
+		return resultCode;
+	}
+	
+	HtiSoapHandlerInterface* handler =
+        static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	if (handler->WaitForHtiMessage(g_ftpHtiTimeoutData) )
+	{
+		if (!handler->IsReceivedHtiError())
+		{
+			array.__size = 0;
+			array.__ptr = 0;
+            DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+			BYTE* body = (BYTE*)(handler->ReceivedHtiMessageBody());
+            int offset = 0;
+			//first byte is the number of elements
+			int numOfElements = body[offset];
+            offset++;
+
+            array.__size = numOfElements;
+			array.__ptr = (ns1__HtiDriveInfo*) soap_malloc(
+                    soap, sizeof(ns1__HtiDriveInfo)*array.__size );
+
+			int i;
+			for(i=0; i<array.__size; ++i)
+			{
+                int rootPathLength = body[offset];
+                offset++;
+				array.__ptr[i].rootPath =
+                    (wchar_t*)soap_malloc(soap, 2*rootPathLength + 2);
+				memcpy(array.__ptr[i].rootPath, body + offset, 2*rootPathLength);
+                (array.__ptr[i].rootPath)[rootPathLength] = 0; //null char
+                offset += 2*rootPathLength;
+                array.__ptr[i].mediaType = (ns1__driveMediaType)body[offset];
+                offset++;
+                array.__ptr[i].uniqueID = *(int*)(body + offset);
+                offset += sizeof(int);
+                array.__ptr[i].driveSize = *(ULONG64*)(body + offset);
+                offset += sizeof(ULONG64);
+                array.__ptr[i].freeSpace = *(ULONG64*)(body + offset);
+                offset += sizeof(ULONG64);
+                int nameLength = body[offset];
+                offset++;
+                array.__ptr[i].driveName = 
+                    (wchar_t*)soap_malloc(soap, 2*nameLength + 2);
+                memcpy(array.__ptr[i].driveName, body + offset, 2*nameLength);
+                (array.__ptr[i].driveName)[nameLength] = 0; //null char
+                offset += 2*nameLength;
+            }
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			resultCode = SOAP_FAULT;
+		}
+	}
+	else
+	{
+		soap->error = soap_receiver_fault(soap,
+										  "Failed receive hti message", NULL);
+		resultCode = SOAP_FAULT;
+	}
+
+    return resultCode;
+}
+
+int sendBinary(struct soap *soap, char* data, const DWORD dataSize )
+{
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	DWORD offset = 0;
+
+    // dataSize == 0 means that uploading empty file - we need to send one
+    // empty data message, so needs to go to following while once
+	while( offset < dataSize || ( offset == 0 && dataSize == 0 ) )
+	{
+		handler->SendHtiMessage( HTI_UID,
+					data + offset,
+					offset + MAX_HTI_MSG_SIZE > dataSize ? dataSize - offset : MAX_HTI_MSG_SIZE
+					);
+		offset += MAX_HTI_MSG_SIZE;
+		//check for error messages
+		if (handler->WaitForHtiMessage(0) ) 
+		{
+			if ( handler->IsReceivedHtiError() )
+			{
+				handler->SendSoapFaultFromReceivedHtiError();
+			}
+			else
+			{
+				soap->error = soap_receiver_fault(soap,
+												"Not expected hti message", NULL);
+			}
+			return SOAP_FAULT;
+		}
+	}
+
+	return SOAP_OK;
+}
+
+int sendSTOR(struct soap *soap,
+             const wchar_t* arg,
+			 const DWORD fileSize )
+{
+	int resultCode = SOAP_OK;
+	
+	int textLen = (int)wcslen( arg );
+
+	if ( !arg || textLen > 0xFF )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		resultCode = SOAP_FAULT;
+		return resultCode;
+	}
+
+	int	bodyLen = 2*textLen + 6;
+
+	BYTE* msgBody = new BYTE[ bodyLen ];
+	msgBody[0] = CMD_FTP_STOR;
+	*((DWORD*)(msgBody + 1)) = fileSize;
+	msgBody[5] = textLen;
+	memcpy( msgBody + 6, arg, 2*textLen );
+
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+	handler->SendHtiMessage(HTI_UID, msgBody, bodyLen, CONTROL_PRIORITY );
+
+	delete[] msgBody;
+	return resultCode;
+}
+
+int ns1__putFile(struct soap* soap,
+				 struct ns1__HtiSoapAttachment *file,
+				 wchar_t *targetPath,
+				 struct ns1__putFileResponse *out)
+{
+	int resultCode;
+	//send attachment as several hti ftp data messages
+	if ( file == NULL || targetPath == NULL )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+	else if ( file->href != NULL )
+	{
+		for (soap_multipart::iterator attachment = (*soap).dime.begin();
+				attachment != (*soap).dime.end(); ++attachment) 
+		{
+			if ( (*attachment).id && strcmp((*attachment).id, file->href)==0 )
+			{
+				resultCode = sendSTOR(soap, targetPath, (*attachment).size );
+				if ( resultCode != SOAP_OK )
+				{
+					return resultCode;
+				}
+				resultCode = receiveFtpOk(soap, g_ftpHtiTimeoutControl);
+				if ( resultCode != SOAP_OK )
+				{
+					return resultCode;
+				}
+				resultCode = sendBinary( soap, (*attachment).ptr, (*attachment).size );
+				if ( resultCode != SOAP_OK )
+				{
+					return resultCode;
+				}
+				return receiveFtpOk(soap, g_ftpHtiTimeoutData); 
+			}
+		} 
+	}
+	else
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+
+	soap->error = soap_sender_fault(soap, "Invalid attachment", NULL);
+	resultCode = SOAP_FAULT;
+
+	return resultCode;
+}
+
+int ns1__getFile(struct soap* soap,
+				 wchar_t *filePath,
+				 struct ns1__getFileResponse &r)
+{
+	int resultCode = SOAP_OK;
+
+	if ( filePath == NULL )
+	{
+		soap->error = soap_sender_fault(soap, "Invalid arguments", NULL);
+		return SOAP_FAULT;
+	}
+
+	resultCode = sendHtiMessage( soap, CMD_FTP_RETR, filePath );
+
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+
+    //receive FILESIZE message
+	DWORD fileSize = 0;
+	if (handler->WaitForHtiMessage(g_ftpHtiTimeoutControl) )
+	{
+		if ( !handler->IsReceivedHtiError() )
+		{
+			DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+			BYTE* body = (BYTE*)(handler->ReceivedHtiMessageBody());
+
+			if ( bodySize == 5 && body[0] == CMD_FTP_FILESIZE )
+			{
+				fileSize = *((DWORD*)(body + 1));
+			}
+			else
+			{
+				soap->error = soap_receiver_fault(soap,
+												"Received invalid hti message", NULL);
+				return SOAP_FAULT;
+			}
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			return SOAP_FAULT;
+		}
+	}
+	else
+	{
+		soap->error = soap_receiver_fault(soap,
+										  "Failed receive hti message", NULL);
+		return SOAP_FAULT;
+	}
+	
+	//receive data messages
+	DWORD receivedFile = 0;
+	char* body = (char*)soap_malloc(soap, fileSize );
+
+	while ( receivedFile < fileSize )
+	{
+		if (handler->WaitForHtiMessage(g_ftpHtiTimeoutData) )
+		{
+			if ( !handler->IsReceivedHtiError() )
+			{
+				//extract response
+				DWORD bodySize = handler->ReceivedHtiMessageBodySize();
+				memcpy( body + receivedFile,
+					   (char*)(handler->ReceivedHtiMessageBody()),
+					   bodySize );
+				receivedFile += bodySize;
+			}
+			else
+			{
+				handler->SendSoapFaultFromReceivedHtiError();
+				return SOAP_FAULT;
+			}
+		}
+		else
+		{
+			soap->error = soap_receiver_fault(soap,
+											"Failed receive hti message", NULL);
+			return SOAP_FAULT;
+		}
+	}
+
+	//create attachment
+	int pLen = (int)wcslen(filePath)+1;
+	r._return.href = (char*)soap_malloc(soap, pLen );
+	WideCharToMultiByte(CP_ACP, 0, filePath, -1, r._return.href, pLen, NULL, NULL);
+
+	r._return.mimeType = (char*)soap_malloc(soap, strlen(fileMimeType)+1 );
+	strcpy( r._return.mimeType, fileMimeType );
+
+	//pass result as DIME attachment
+	soap_set_dime(soap);
+	resultCode = soap_set_dime_attachment(soap,
+								body,
+								fileSize,
+								r._return.mimeType,
+								r._return.href,
+								0, NULL);
+	if (  resultCode != SOAP_OK )
+	{
+		//Util::Debug("soap_set_dime_attachment failed");
+		soap_clr_dime(soap);
+		soap->error = soap_receiver_fault(soap,
+								"Failed create DIME attachment", NULL);
+	}
+	
+	return resultCode;
+}
+
+int ns1__cancelFileTransfer(struct soap* soap,
+							void *_,
+							struct ns1__cancelFileTransferResponse *out)
+{
+	int resultCode = sendHtiMessage( soap, CMD_FTP_CANCEL, NULL );
+	if ( resultCode != SOAP_OK )
+	{
+		return resultCode;
+	}
+	
+	return receiveFtpOk(soap, g_ftpHtiTimeoutControl);
+}
+
+int ns1__listFiles(struct soap* soap,
+				   wchar_t *targetDir,
+				   struct ArrayOfStrings &dirs)
+{
+	return sendHtiMessageAndReceiveStringArray( soap, CMD_FTP_LIST, targetDir, dirs );
+}
+
+int ns1__listFilesSizes(struct soap* soap,
+                        wchar_t *targetDir,
+                        struct ArrayOfHtiFileInfos &fileInfos)
+{
+    return sendHtiMessageAndReceiveHtiFileInfoArray( soap, CMD_FTP_LISTSIZE,
+                                                     targetDir, fileInfos );
+}
+
+int ns1__listDirs(struct soap* soap,
+				  wchar_t *targetDir,
+				  struct ArrayOfStrings &files)
+{
+	return sendHtiMessageAndReceiveStringArray( soap, CMD_FTP_LISTDIR, targetDir, files );
+}
+
+int ns1__createDir(struct soap* soap,
+				   wchar_t *targetDir,
+				   struct ns1__createDirResponse *out)
+{
+	return sendHtiMessageAndReceiveOK( soap, CMD_FTP_MKD, targetDir );
+}
+
+int ns1__deleteDir(struct soap* soap,
+				   wchar_t *targetDir,
+				   struct ns1__deleteDirResponse *out)
+{
+	return sendHtiMessageAndReceiveOK( soap, CMD_FTP_RMD, targetDir );
+}
+
+int ns1__deleteFile(struct soap* soap,
+					wchar_t *targetFile,
+					struct ns1__deleteFileResponse *out)
+{
+	return sendHtiMessageAndReceiveOK( soap, CMD_FTP_DELE, targetFile );
+}
+
+
+int send_receive_htimessage(struct soap* soap, BYTE **msgBody, int &msgBodyLen, int timeout)
+{
+	// Send the message to symbian side
+	HtiSoapHandlerInterface* handler = static_cast<HtiSoapHandlerInterface*>(soap->user);
+	handler->SendHtiMessage(HTI_UID, *msgBody, msgBodyLen, CONTROL_PRIORITY);
+
+	// Clean these up for received HTI message
+	delete *msgBody;
+	*msgBody = NULL;
+	msgBodyLen = 0;
+
+	// ...and wait for OK or error msg
+	if (handler->WaitForHtiMessage(timeout))
+	{
+		if ( !handler->IsReceivedHtiError() )
+		{
+			// Get received message
+			*msgBody = (BYTE*) handler->ReceivedHtiMessageBody();
+			msgBodyLen = handler->ReceivedHtiMessageBodySize();
+			return ERROR_SUCCESS;
+		}
+		else
+		{
+			handler->SendSoapFaultFromReceivedHtiError();
+			return ERROR_GEN_FAILURE;
+		}
+	}
+	// ...or timeout
+	else
+	{
+		soap->error = soap_receiver_fault(soap, "HtiGateway", "No response from symbian side");
+		return WAIT_TIMEOUT;
+	}
+}
+
+int ns1__setForcedOperations(struct soap* soap,
+							 bool state, 
+                             struct ns1__setForcedOperationsResponse *out)
+{
+	int msgBodyLen = 1+1;
+	BYTE *msgBody = new BYTE[msgBodyLen];
+	msgBody[0] = CMD_FTP_SETFORCE;
+	msgBody[1] = (BYTE) state;
+
+	if( send_receive_htimessage(soap, &msgBody, msgBodyLen, g_ftpHtiTimeoutControl) 
+        != ERROR_SUCCESS )
+		return SOAP_FAULT;
+
+	if(msgBody[0] != CMD_FTP_OK)
+	{
+		soap->error = soap_receiver_fault(soap, "HtiError", "Operation failed. Response code not ok.");
+		return SOAP_FAULT;
+	}
+
+	return SOAP_OK;
+}
+
+int ns1__fileChecksum(struct soap* soap, 
+					  unsigned char algorithmId, 
+					  wchar_t *targetFile, 
+                      struct ArrayOfBytes &checksumByteArray)
+{
+	int targetFileLen = targetFile ? (int) wcslen(targetFile) : 0;
+	if(targetFileLen == 0)
+	{
+		soap->error = soap_receiver_fault(soap, "HtiGateway", "targetFile parameter missing");
+		return SOAP_FAULT;
+	}
+
+	int msgBodyLen = 1+1+1+targetFileLen*2;
+	BYTE *msgBody = new BYTE[msgBodyLen];
+	msgBody[0] = CMD_FTP_CHECKSUM_U;
+	msgBody[1] = algorithmId;
+	msgBody[2] = targetFileLen;
+	memcpy(msgBody+3, targetFile, targetFileLen*2);
+
+	if( send_receive_htimessage(soap, &msgBody, msgBodyLen, g_ftpHtiTimeoutControl) 
+        != ERROR_SUCCESS )
+		return SOAP_FAULT;
+
+	checksumByteArray.__size = msgBodyLen;
+	checksumByteArray.__ptr = (BYTE*)soap_malloc(soap, sizeof(BYTE)*checksumByteArray.__size );
+
+	memcpy(checksumByteArray.__ptr, msgBody, msgBodyLen);
+
+	return SOAP_OK;
+}
+
+int ns1__format(struct soap* soap,
+				unsigned char drive, 
+                unsigned char formatMode,
+                struct ns1__formatResponse *out)
+{
+	int msgBodyLen = 3;
+	BYTE *msgBody = new BYTE[msgBodyLen];
+	msgBody[0] = CMD_FTP_FORMAT;
+	msgBody[1] = (BYTE) drive;
+    msgBody[2] = (BYTE) formatMode;
+
+    // might take long with large memory cards
+	if( send_receive_htimessage(soap, &msgBody, msgBodyLen, g_ftpHtiTimeoutData) 
+        != ERROR_SUCCESS )
+		return SOAP_FAULT;
+
+	if(msgBody[0] != CMD_FTP_OK)
+	{
+		soap->error = soap_receiver_fault(soap, "HtiError", "Operation failed. Response code not ok.");
+		return SOAP_FAULT;
+	}
+
+	return SOAP_OK;
+}
+
+int ns1__listDrives(struct soap* soap,
+                    void *_,
+                    struct ArrayOfHtiDriveInfos &driveInfos)
+{
+    return sendHtiMessageAndReceiveHtiDriveInfoArray( soap, CMD_FTP_LISTDRIVES,
+                                                     driveInfos );
+}
+