BluetoothOppObexSession.java
@Override
public int onPut(Operation op) {
if (D) {
Log.d(TAG, "onPut " + op.toString());
}
/* For multiple objects, reject further objects after the user denies the first one */
if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED) {
return ResponseCodes.OBEX_HTTP_FORBIDDEN;
}
String destination;
if (mTransport instanceof BluetoothObexTransport) {
destination = ((BluetoothObexTransport) mTransport).getRemoteAddress();
} else {
destination = "FF:FF:FF:00:00:00";
}
boolean isWhitelisted =
BluetoothOppManager.getInstance(mContext).isWhitelisted(destination);
HeaderSet request;
String name, mimeType;
Long length;
try {
request = op.getReceivedHeader();
if (V) {
Constants.logHeader(request);
}
name = (String) request.getHeader(HeaderSet.NAME);
length = (Long) request.getHeader(HeaderSet.LENGTH);
mimeType = (String) request.getHeader(HeaderSet.TYPE);
} catch (IOException e) {
Log.e(TAG, "onPut: getReceivedHeaders error " + e);
return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
}
if (length == 0) {
if (D) {
Log.w(TAG, "length is 0, reject the transfer");
}
return ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED;
}
if (name == null || name.isEmpty()) {
if (D) {
Log.w(TAG, "name is null or empty, reject the transfer");
}
return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
}
// First we look for the mime type in the Android map
String extension, type;
int dotIndex = name.lastIndexOf(".");
if (dotIndex < 0 && mimeType == null) {
if (D) {
Log.w(TAG, "There is no file extension or mime type, reject the transfer");
}
return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
} else {
extension = name.substring(dotIndex + 1).toLowerCase();
MimeTypeMap map = MimeTypeMap.getSingleton();
type = map.getMimeTypeFromExtension(extension);
if (V) {
Log.v(TAG, "Mimetype guessed from extension " + extension + " is " + type);
}
if (type != null) {
mimeType = type;
} else {
if (mimeType == null) {
if (D) {
Log.w(TAG, "Can't get mimetype, reject the transfer");
}
return ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
}
}
mimeType = mimeType.toLowerCase();
}
Log.w(TAG, "mimeType = " + mimeType );
Log.w(TAG, "isWhitelisted = " + isWhitelisted );
Log.w(TAG, "Constants.ACCEPTABLE_SHARE_INBOUND_TYPES = " + Constants.ACCEPTABLE_SHARE_INBOUND_TYPES );
// Reject anything outside the "whitelist" plus unspecified MIME Types.
if (mimeType == null || (!isWhitelisted && !Constants.mimeTypeMatches(mimeType,
Constants.ACCEPTABLE_SHARE_INBOUND_TYPES))) {
if (D) {
Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer");
}
//return ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
//各种条件判断 黑白名单 直接忽略判断的结果 不管啥文件 让流程往下走就好了
}
ContentValues values = new ContentValues();
values.put(BluetoothShare.FILENAME_HINT, name);
values.put(BluetoothShare.TOTAL_BYTES, length);
values.put(BluetoothShare.MIMETYPE, mimeType);
values.put(BluetoothShare.DESTINATION, destination);
values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND);
values.put(BluetoothShare.TIMESTAMP, mTimestamp);
// It's not first put if !serverBlocking, so we auto accept it
if (!mServerBlocking && (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED
|| mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED)) {
values.put(BluetoothShare.USER_CONFIRMATION,
BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED);
}
if (isWhitelisted) {
values.put(BluetoothShare.USER_CONFIRMATION,
BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
}
Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
mLocalShareInfoId = Integer.parseInt(contentUri.getPathSegments().get(1));
if (V) {
Log.v(TAG, "insert contentUri: " + contentUri);
Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId);
}
synchronized (this) {
mPartialWakeLock.acquire();
mServerBlocking = true;
try {
while (mServerBlocking) {
wait(1000);
if (mCallback != null && !mTimeoutMsgSent) {
mCallback.sendMessageDelayed(mCallback.obtainMessage(
BluetoothOppObexSession.MSG_CONNECT_TIMEOUT),
BluetoothOppObexSession.SESSION_TIMEOUT);
mTimeoutMsgSent = true;
if (V) {
Log.v(TAG, "MSG_CONNECT_TIMEOUT sent");
}
}
}
} catch (InterruptedException e) {
if (V) {
Log.v(TAG, "Interrupted in onPut blocking");
}
}
}
if (D) {
Log.d(TAG, "Server unblocked ");
}
synchronized (this) {
if (mCallback != null && mTimeoutMsgSent) {
mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
}
}
/* we should have mInfo now */
/*
* TODO check if this mInfo match the one that we insert before server
* blocking? just to make sure no error happens
*/
if (mInfo.mId != mLocalShareInfoId) {
Log.e(TAG, "Unexpected error!");
}
mAccepted = mInfo.mConfirm;
if (V) {
Log.v(TAG, "after confirm: userAccepted=" + mAccepted);
}
int status = BluetoothShare.STATUS_SUCCESS;
int obexResponse = ResponseCodes.OBEX_HTTP_OK;
if (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED
|| mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED
|| mAccepted == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED) {
/* Confirm or auto-confirm */
mNumFilesAttemptedToReceive++;
if (mFileInfo.mFileName == null) {
status = mFileInfo.mStatus;
/* TODO need to check if this line is correct */
mInfo.mStatus = mFileInfo.mStatus;
Constants.updateShareStatus(mContext, mInfo.mId, status);
obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
if (mFileInfo.mFileName != null) {
ContentValues updateValues = new ContentValues();
contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName);
updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING);
mContext.getContentResolver().update(contentUri, updateValues, null, null);
status = receiveFile(mFileInfo, op);
/*
* TODO map status to obex response code
*/
if (status != BluetoothShare.STATUS_SUCCESS) {
obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
}
Constants.updateShareStatus(mContext, mInfo.mId, status);
}
if (status == BluetoothShare.STATUS_SUCCESS) {
Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE);
msg.obj = mInfo;
msg.sendToTarget();
} else {
if (mCallback != null) {
Message msg =
Message.obtain(mCallback, BluetoothOppObexSession.MSG_SESSION_ERROR);
mInfo.mStatus = status;
msg.obj = mInfo;
msg.sendToTarget();
}
}
} else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED
|| mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) {
/* user actively deny the inbound transfer */
/*
* Note There is a question: what's next if user deny the first obj?
* Option 1 :continue prompt for next objects
* Option 2 :reject next objects and finish the session
* Now we take option 2:
*/
Log.i(TAG, "Rejected incoming request");
if (mFileInfo.mFileName != null) {
try {
mFileInfo.mOutputStream.close();
} catch (IOException e) {
Log.e(TAG, "error close file stream");
}
new File(mFileInfo.mFileName).delete();
}
// set status as local cancel
status = BluetoothShare.STATUS_CANCELED;
Constants.updateShareStatus(mContext, mInfo.mId, status);
obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN;
Message msg = Message.obtain(mCallback);
msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED;
mInfo.mStatus = status;
msg.obj = mInfo;
msg.sendToTarget();
}
return obexResponse;
}