예제 #1
0
	/**
	 * Return a FileSystem object.
	 */
	void PhoneGapFile::actionRequestFileSystem(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		// We support only persistent storage.
		int type = message.getArgsFieldInt("type");
		if (LOCALFILESYSTEM_PERSISTENT != type)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Size parameter must be zero.
		int size = message.getArgsFieldInt("size");
		if (0 != size)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// TODO: Replace hard-coded path with platform aware path handling.
		String rootEntry = emitDirectoryEntry("sdcard", "/sdcard");
		String fileSystemInfo = emitFileSystemInfo("persistent", rootEntry);
		callSuccess(
			callbackID,
			fileSystemInfo,
			"window.localFileSystem._castFS");
	}
예제 #2
0
	/**
	 * Implementation of capture API:s exposed to JavaScript.
	 * @return true if message was handled, false if not.
	 */
	void PhoneGapCamera::handleMessage(JSONMessage& message)
	{
		if (message.getParam("action") == "getPicture")
		{
			MYLOG("PhoneGapCamera::handleMessage getPicture");

			mCaptureCallBack = message.getParam("PhoneGapCallBackId");

			//maImagePickerOpen() #EVENT_TYPE_IMAGE_PICKER

			/*
			struct {
				// #EVENT_TYPE_IMAGE_PICKER events, this will be 0 if canceled or 1 if Ok was pressed.
				int imagePickerState;
				// #EVENT_TYPE_IMAGE_PICKER event, contains the new handle to the selected image.
				MAHandle imagePickerItem;
			} imagePicker;
			*/

			mMessageHandler->callSuccess(
				mCaptureCallBack,
				PHONEGAP_CALLBACK_STATUS_OK,
				"{\"message\":\"Hello\"}",
				false);

			/*int duration = message.getArgsFieldInt("duration");
			if(duration > 0)
			{
				char durationString[16];
				maCaptureSetProperty(MA_CAPTURE_MAX_DURATION, itoa(duration,durationString,10));
			}

			mCaptureCallBack = message.getParam("PhoneGapCallBackId");

			int result = maCaptureAction(MA_CAPTURE_ACTION_RECORD_VIDEO);

			if(result == MA_CAPTURE_RES_CAMERA_NOT_AVAILABLE)
			{
				//Camera was busy by another app
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_APPLICATION_BUSY\"}",
					false);
			}
			else if(result == MA_CAPTURE_RES_VIDEO_NOT_SUPPORTED)
			{
				//No camera
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_NOT_SUPPORTED\"}",
					false);
			}
			*/
		}
	}
예제 #3
0
	/**
	 * Return a FileEntry object.
	 */
	void PhoneGapFile::actionGetFile(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fullPath");
		String path = message.getArgsField("path");
		String fullFilePath = fullPath + "/" + path;

		// Get flags "create" and "exclusive".
		bool create = false;
		bool exclusive = false;
		bool success = message.getJSONParamsOptionsCreateExclusive(create, exclusive);
		if (!success)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Create file if requested.
		if (create)
		{
			if (exclusive)
			{
				// The file must not exist if "exclusive" is true.
				if (FileExists(fullFilePath))
				{
					callFileError(callbackID, FILEERROR_PATH_EXISTS_ERR);
					return;
				}
			}

			if (!FileExists(fullFilePath))
			{
				// Create the file.
				bool created = FileCreatePath(fullFilePath);
				if (!created)
				{
					callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
					return;
				}
			}
		}

		// Send back FileEntry data.
		String fileEntry = emitFileEntry(
			path,
			fullFilePath);
		callSuccess(
			callbackID,
			fileEntry,
			"window.localFileSystem._castEntry");
	}
예제 #4
0
	/**
	 * Return a Metadata object.
	 */
	void PhoneGapFile::actionGetMetadata(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fullPath");

		String metadata = emitMetadata(
			FileGetDate(fullPath));

		// Note that _castDate is used here.
		callSuccess(
			callbackID,
			metadata,
			"window.localFileSystem._castDate");
	}
예제 #5
0
	/**
	 * This is only valid for directories.
	 */
	void PhoneGapFile::actionRemoveRecursively(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String path = message.getArgsField("fullPath");

		int result = FileDeleteDirectory(path);
		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
			return;
		}

		callSuccess(callbackID, "\"ok\"");
	}
예제 #6
0
	void PhoneGapFile::actionTruncate(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fileName");

		int size = message.getArgsFieldInt("size");

		int result = FileTruncate(fullPath, size);
		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
			return;
		}

		// Send back the result, the new length of the file.
		char lengthBuf[32];
		sprintf(lengthBuf, "%i", result);
		callSuccess(callbackID, lengthBuf);
	}
예제 #7
0
	void PhoneGapFile::actionResolveLocalFileSystemURI(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String uri = message.getArgsField("uri");

		// Get path.
		const char* pURL = uri.c_str();
		const char* pPath = strstr(pURL, "file://");
		if (NULL == pPath)
		{
			callFileError(callbackID, "1000");
			return;
		}
		if (pURL != pPath)
		{
			callFileError(callbackID, FILEERROR_SYNTAX_ERR);
			return;
		}

		// Move to after "file://"
		pPath += 7;

		// Check that this is an existing directory.
		if (!FileIsDirectory(pPath))
		{
			callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
			return;
		}

		String entry = emitDirectoryEntry(
			FileGetName(pPath),
			pPath);
		callSuccess(
			callbackID,
			entry,
			"window.localFileSystem._castEntry");


	}
예제 #8
0
	/**
	 * Return a File object.
	 */
	void PhoneGapFile::actionGetFileMetadata(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fullPath");

		char sizeBuf[64];
		sprintf(sizeBuf, "%i", FileGetSize(fullPath));

		String file = emitFile(
			FileGetName(fullPath),
			fullPath,
			FileGetMimeType(fullPath),
			FileGetDate(fullPath),
			sizeBuf);

		// Note that _castDate also casts a File object.
		callSuccess(
			callbackID,
			file,
			"window.localFileSystem._castDate");
	}
예제 #9
0
	void PhoneGapFile::actionWrite(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fileName");
		String data = message.getArgsField("data");
		int position = message.getArgsFieldInt("position");

		int result = FileWrite(fullPath, data, position);
		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Send back the new file size.
		char sizeBuf[32];
		sprintf(sizeBuf, "%i", FileGetSize(fullPath));
		callSuccess(
			callbackID,
			sizeBuf);
	}
예제 #10
0
	void PhoneGapFile::actionReadAsDataURL(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fileName");

		String content;
		int result = FileRead(fullPath, content);
		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		String base64URL = "\"data:";
		base64URL += FileGetMimeType(fullPath);
		base64URL += ";base64,";
		base64URL += JSONMessage::base64Encode(content.c_str());
		base64URL += "\"";

		// Send back the file content.
		callSuccess(callbackID, base64URL);
	}
예제 #11
0
	void PhoneGapFile::actionReadAsText(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fileName");

		// TODO: Encoding param is not used. This is the requested
		// encoding of the data send back to PhoneGap.
		//String encoding = message.getArgsField("encoding");

		String content;
		int result = FileRead(fullPath, content);
		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Send back the file content.
		callSuccess(
			callbackID,
			JSONMessage::JSONStringify(content.c_str()));
	}
예제 #12
0
	/**
	 * Implementation of PhoneGap and other APIs exposed in JavaScript.
	 * This function is used to detect different messages and call the
	 * respective function in MoSync.
	 *
	 * @return true if message was handled, false if not.
	 */
	bool PhoneGapMessageHandler::handlePhoneGapMessage(JSONMessage& message)
	{
		// MoSync servcies implemented on top of the PhoneGap protocol
		// for convenience. We can move this to its own message handler
		// at a later point.
		if ((message.getParam("service") == "mosync") &&
			(message.getParam("action") == "mosync.notification.messageBox"))
		{
			String titleText = message.getParam("title");
			String messageText = message.getParam("message");
			maMessageBox(titleText.c_str(), messageText.c_str());
		}
		// Send device information to PhoneGap
		else if ((message.getParam("service") == "Device") &&
				(message.getParam("action") == "getDeviceInfo"))
		{
			sendDeviceProperties(message.getParam("PhoneGapCallBackId"));
		}
		// Process the vibration message
		else if ((message.getParam("service") == "Notification") &&
				(message.getParam("action") == "vibrate"))
		{
			int duration = message.getArgsFieldInt(0);
			maVibrate(duration);
		}
		//Process the beep message
		else if ((message.getParam("service") == "Notification") &&
				(message.getParam("action") == "beep"))
		{
			int repeatCount = message.getArgsFieldInt(0);
			for (int i = 0; i < repeatCount; i++)
			{
				if (mBeepSound > 0)
				{
					maSoundPlay(mBeepSound, 0, maGetDataSize(mBeepSound));
				}
			}
		}
		else if ((message.getParam("service") == "NetworkStatus") &&
				(message.getParam("action") == "getConnectionInfo"))
		{
			sendConnectionType(message.getParam("PhoneGapCallBackId"));
		}
		else if ((message.getParam("service") == "Accelerometer")
			|| (message.getParam("service") == "GeoLocation")
			|| (message.getParam("service") == "Compass"))
		{
			mPhoneGapSensors->handleMessage(message);
		}
		else if (message.getParam("service") == "SensorManager")
		{
			mSensorManager->handleMessage(message);
		}
		else if (message.getParam("service") == "File")
		{
			mPhoneGapFile->handleFileMessage(message);
		}
		else if (message.getParam("service") == "FileTransfer")
		{
			mPhoneGapFile->handleFileTransferMessage(message);
		}
		else if (message.getParam("service") == "PushNotification")
		{
			mPushNotificationManager->handleMessage(message);
		}
		else if (message.getParam("service") == "Capture")
		{
			mPhoneGapCapture->handleMessage(message);
		}
//		else if (message.getParam("service") == "Camera")
//		{
//			mPhoneGapCamera->handleMessage(message);
//		}
		else
		{
			// Message was not handled.
			return false;
		}

		// Message was handled.
		return true;
	}
예제 #13
0
	/**
	 * Implementation of capture API:s exposed to JavaScript.
	 * @return true if message was handled, false if not.
	 */
	void PhoneGapCapture::handleMessage(JSONMessage& message)
	{
		if(message.getParam("action") == "captureVideo")
		{
			int duration = message.getArgsFieldInt("duration");
			if(duration > 0)
			{
				char durationString[16];
				maCaptureSetProperty(MA_CAPTURE_MAX_DURATION, itoa(duration,durationString,10));
			}

			mCaptureCallBack = message.getParam("PhoneGapCallBackId");

			int result = maCaptureAction(MA_CAPTURE_ACTION_RECORD_VIDEO);

			if(result == MA_CAPTURE_RES_CAMERA_NOT_AVAILABLE)
			{
				//Camera was busy by another app
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_APPLICATION_BUSY\"}",
					false);
			}
			else if(result == MA_CAPTURE_RES_VIDEO_NOT_SUPPORTED)
			{
				//No camera
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_NOT_SUPPORTED\"}",
					false);
			}
		}
		else if(message.getParam("action") == "captureImage")
		{
			mCaptureCallBack = message.getParam("PhoneGapCallBackId");

			int result = maCaptureAction(MA_CAPTURE_ACTION_TAKE_PICTURE);

			if(result == MA_CAPTURE_RES_CAMERA_NOT_AVAILABLE)
			{
				//Camera was busy by another app
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_APPLICATION_BUSY\"}",
					false);
			}
			if(result == MA_CAPTURE_RES_PICTURE_NOT_SUPPORTED)
			{
				//No camera
				mMessageHandler->callError(
					mCaptureCallBack,
					PHONEGAP_CALLBACK_STATUS_ERROR,
					"{\"code\":\"CAPTURE_NOT_SUPPORTED\"}",
					false);
			}
		}
		else if(message.getParam("action") == "captureAudio")
		{
			//MoSync does not support audio capture
			mMessageHandler->callError(
				mCaptureCallBack,
				PHONEGAP_CALLBACK_STATUS_ERROR,
				"{\"code\":\"CAPTURE_NOT_SUPPORTED\"}",
				false);
		}
	}
예제 #14
0
	/**
	 * Return a DirectoryEntry object.
	 */
	void PhoneGapFile::actionGetDirectory(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String fullPath = message.getArgsField("fullPath");
		String path = message.getArgsField("path");
		String fullFilePath = fullPath + "/" + path;

		// Add a trailing slash if not present. MoSync API requires this.
		if (fullFilePath[fullFilePath.size() - 1] != '/')
		{
			fullFilePath += "/";
		}

		// Get flags "create" and "exclusive".
		bool create = false;
		bool exclusive = false;
		bool success = message.getJSONParamsOptionsCreateExclusive(create, exclusive);
		if (!success)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Create directory if requested.
		if (create)
		{
			if (exclusive)
			{
				// The file must not exist if "exclusive" is true.
				if (FileExists(fullFilePath))
				{
					callFileError(callbackID, FILEERROR_PATH_EXISTS_ERR);
					return;
				}
			}

			if (!FileExists(fullFilePath))
			{
				// Create the directory.
				// TODO: Invoke error if parent directory does not
				// exist to be compatible with the PhoneGap spec.
				bool created = FileCreatePath(fullFilePath);
				if (!created)
				{
					callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
					return;
				}
			}
		}

		// Send back DirectoryEntry data.
		String directoryEntry = emitDirectoryEntry(
			path,
			// Remove the trailing slash from the full path.
			fullFilePath.substr(0, fullFilePath.size() - 1));
		callSuccess(
			callbackID,
			directoryEntry,
			"window.localFileSystem._castEntry");
	}
예제 #15
0
	/**
	 * Implementation of File API exposed to JavaScript.
	 * @return true if message was handled, false if not.
	 */
	void PhoneGapFile::handleMessage(JSONMessage& message)
	{
		if (message.getParam("action") == "requestFileSystem")
		{
			actionRequestFileSystem(message);
		}
		else if (message.getParam("action") == "resolveLocalFileSystemURI")
		{
			actionResolveLocalFileSystemURI(message);
		}
		else if (message.getParam("action") == "getFile")
		{
			actionGetFile(message);
		}
		else if (message.getParam("action") == "getDirectory")
		{
			actionGetDirectory(message);
		}
		else if (message.getParam("action") == "getFileMetadata")
		{
			actionGetFileMetadata(message);
		}
		else if (message.getParam("action") == "getMetadata")
		{
			actionGetMetadata(message);
		}
		else if (message.getParam("action") == "write")
		{
			actionWrite(message);
		}
		else if (message.getParam("action") == "readAsText")
		{
			actionReadAsText(message);
		}
		else if (message.getParam("action") == "readAsDataURL")
		{
			actionReadAsDataURL(message);
		}
		else if (message.getParam("action") == "truncate")
		{
			actionTruncate(message);
		}
		else if (message.getParam("action") == "copyTo")
		{
			actionCopyTo(message);
		}
		else if (message.getParam("action") == "moveTo")
		{
			actionMoveTo(message);
		}
		else if (message.getParam("action") == "remove")
		{
			actionRemove(message);
		}
		else if (message.getParam("action") == "removeRecursively")
		{
			actionRemoveRecursively(message);
		}
		else if (message.getParam("action") == "readEntries")
		{
			actionReadEntries(message);
		}
	}
예제 #16
0
	// mosync://PhoneGap?service=File&action=readEntries&args={"fullPath":"/mnt/sdcard/fob1"}&
	// PhoneGapCallBackId=File21
	void PhoneGapFile::actionReadEntries(JSONMessage& message)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String path = message.getArgsField("fullPath");

		// Open entry array.
		String entries = "[";

		char nameBuf[2048];

		// Make sure path end with a slash.
		FileMakeDirectoryPath(path);

		// Open directory listing.
		MAHandle list = maFileListStart(
			path.c_str(),
			"",
			MA_FL_SORT_NAME | MA_FL_ORDER_ASCENDING);
		if (list < 0)
		{
			callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
			return;
		}

		// List all files in this directory.
		while (true)
		{
			// Move to next file.
			int result = maFileListNext(list, nameBuf, 2048);
			if (0 == result)
			{
				// No more files.
				break;
			}
			if (0 > result)
			{
				maFileListClose(list);
				callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
				return;
			}

			// Add separating comma if needed.
			if (entries.size() > 1)
			{
				entries += ",";
			}

			// Full path to entry.
			String fullPath = path + nameBuf;

			// Is this a directory?
			if ('/' == nameBuf[result - 1])
			{
				// We remove the trailing slash of the directory.
				String pathWithNoSlash = fullPath.substr(0, fullPath.size() - 1);
				String entry = emitDirectoryEntry(
					FileGetName(pathWithNoSlash),
					pathWithNoSlash);
				entries += entry;
			}
			else
			{
				String entry = emitFileEntry(
					FileGetName(fullPath),
					fullPath);
				entries += entry;
			}
		}

		// Close the directory listing.
		maFileListClose(list);

		// Close entry array.
		entries += "]";

		// Return result to PhoneGap.
		callSuccess(
			callbackID,
			entries,
			"window.localFileSystem._castEntries");
	}
예제 #17
0
	/**
	 * Implementation of PhoneGap and other APIs exposed in JavaScript.
	 * This function is used to detect different messages and call the
	 * respective function in MoSync.
	 *
	 * @return true if message was handled, false if not.
	 */
	bool PhoneGapMessageHandler::handlePhoneGapMessage(JSONMessage& message)
	{
		// Send device information to PhoneGap
		if ((message.getParam("service") == "Device") &&
				(message.getParam("action") == "Get"))
		{
			sendDeviceProperties(message.getParam("PhoneGapCallBackId"));
		}
		// Process the vibration message
		else if ((message.getParam("service") == "Notification") &&
				(message.getParam("action") == "vibrate"))
		{
			int duration = message.getArgsFieldInt("duration");
			maVibrate(duration);
		}
		//Process the beep message
		else if ((message.getParam("service") == "Notification") &&
				(message.getParam("action") == "beep"))
		{
			int repeatCount = message.getParamInt("args");
			for (int i = 0; i < repeatCount; i++)
			{
				if (mBeepSound > 0)
				{
					maSoundPlay(mBeepSound, 0, maGetDataSize(mBeepSound));
				}
			}
		}
		else if ((message.getParam("service") == "Connection") &&
				(message.getParam("action") == "getConnectionInfo"))
		{
			sendConnectionType(message.getParam("PhoneGapCallBackId"));
		}
		else if ((message.getParam("service") == "Accelerometer")
			|| (message.getParam("service") == "GeoLocation")
			|| (message.getParam("service") == "Compass"))
		{
			mPhoneGapSensors.handleMessage(message);
		}
		else if (message.getParam("service") == "SensorManager")
		{
			mPhoneGapSensorManager.handleMessage(message);
		}
		else if (message.getParam("service") == "File")
		{
			mPhoneGapFile.handleMessage(message);
		}
		else if (message.getParam("service") == "PushNotification")
		{
			mPushNotificationManager.handleMessage(message);
		}
		else if (message.getParam("service") == "Capture")
		{
			mPhoneGapCapture.handleMessage(message);
		}
		else
		{
			// Message was not handled.
			return false;
		}

		// Message was handled.
		return true;
	}
예제 #18
0
	/**
	 * Implementation of sensor API:s exposed to JavaScript.
	 * @return true if message was handled, false if not.
	 */
	void PhoneGapSensors::handleMessage(JSONMessage& message)
	{
		// Accelerometer request from PhoneGap
		if ((message.getParam("service") == "Accelerometer"))
		{
			if (message.getParam("action") == "getAcceleration")
			{
				processAcelerometerRequest(
					message.getParam("PhoneGapCallBackId"),
					false); //stop Accelerometer after the first run
			}
			else if (message.getParam("action") == "start")
			{
				processAcelerometerRequest(
					message.getParam("PhoneGapCallBackId"),
					true); // Keep the Accelerometer running
			}
			else if (message.getParam("action") == "stop")
			{
				maSensorStop(SENSOR_TYPE_ACCELEROMETER);
				mAccelerometerWatchStarted = false;
			}
		}
		// GeoLocation request from PhoneGap
		else if (message.getParam("service") == "GeoLocation")
		{
			if (message.getParam("action") == "addWatch")
			{
				processLocationRequest(
					message.getParam("PhoneGapCallBackId"),
					true);
			}
			else if (message.getParam("action") == "getLocation")
			{
				processLocationRequest(
					message.getParam("PhoneGapCallBackId"),
					false); //stop GPS after the first run
			}
			else if (message.getParam("action") == "clearWatch")
			{
				maLocationStop();
				mLocationWatchStarted = false;
			}
		}
		// Compass request from PhoneGap
		else if (message.getParam("service") == "Compass")
		{
			if(message.getParam("action") == "getHeading")
			{
				processCompassRequest(
					message.getParam("PhoneGapCallBackId"),
					false); //stop Sensor after the first run
			}
			// Cordova 2.3.0 doesn't use Compass.startWatch
			/* else if (message.getParam("action") == "startWatch")
			{
				processCompassRequest(
					message.getParam("PhoneGapCallBackId"),
					true); // Keep the Compass running
			} */
			else if (message.getParam("action") == "stopHeading")
			{
				maSensorStop(SENSOR_TYPE_COMPASS);
				mAccelerometerWatchStarted = false;
			}
		}
	}
예제 #19
0
	//I/maWriteLog(20616): @@@ URL: mosync://PhoneGap?service=File&action=moveTo&args={"fullPath":"/mnt/sdcard/hello2.txt","pa
	//rent":{"isFile":false,"isDirectory":true,"name":"sdcard","fullPath":"/mnt/sdcard","filesystem":null},"newName":"hello3.t
	//xt"}&PhoneGapCallBackId=File19
	void PhoneGapFile::actionCopyMoveHelper(JSONMessage& message, bool move)
	{
		String callbackID = message.getParam("PhoneGapCallBackId");

		String sourcePath = message.getArgsField("fullPath");

		String destinationName = message.getArgsField("newName");

		// Get the destination path from the JSON tree.
		String destinationPath;
		bool success = message.getJSONParamParentFullPath(destinationPath);
		if (!success)
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Check that we have the required path names.
		if ((sourcePath.size() == 0) ||
			(destinationName.size() == 0) ||
			(destinationPath.size() == 0))
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		bool isDirectory;

		// Check that sourcePath exists.
		if (FileIsDirectory(sourcePath))
		{
			isDirectory = true;
		}
		else if (FileExistsHelper(sourcePath))
		{
			isDirectory = false;
		}
		else
		{
			callFileError(callbackID, FILEERROR_NO_MODIFICATION_ALLOWED_ERR);
			return;
		}

		// Compose the full destination path.
		String fullDestinationPath = destinationPath + "/" + destinationName;

		int result;

		if (move)
		{
			result = FileMove(sourcePath, fullDestinationPath);
		}
		else
		{
			result = FileCopy(sourcePath, fullDestinationPath);
		}

		if (result < 0)
		{
			callFileError(callbackID, FILEERROR_NOT_FOUND_ERR);
			return;
		}

		// Send back entry data.
		String entry;
		if (isDirectory)
		{
			entry = emitDirectoryEntry(
				destinationName,
				fullDestinationPath);
		}
		else
		{
			entry = emitFileEntry(
				destinationName,
				fullDestinationPath);
		}
		callSuccess(
			callbackID,
			entry,
			"window.localFileSystem._castEntry");
	}