diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/PC_Tools/HTIGateway/ServicePlugins/HtiFtp/HtiFtp.cpp --- /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 + +#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(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(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(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%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(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; jSendSoapFaultFromReceivedHtiError(); + 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(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; iSendSoapFaultFromReceivedHtiError(); + 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(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(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(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(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 ); +} +